From 3fe059ad91104bfc5cbfdaeb0864d58e8c758437 Mon Sep 17 00:00:00 2001 From: mwinter Date: Sun, 3 Mar 2024 19:08:30 -0600 Subject: [PATCH] transpositions of coda now done --- lilypond/includes/part_I.ly | 1 + lilypond/includes/part_II.ly | 1 + lilypond/includes/part_III.ly | 1 + lilypond/includes/part_IV.ly | 1 + lilypond/score_template.pdf | Bin 567902 -> 568051 bytes .../edited/seeds_and_ledgers_2.pdf | Bin 922670 -> 917933 bytes .../coda/edited/seeds_and_ledgers_3_coda.pdf | Bin 566361 -> 578451 bytes .../coda/original_output/score_template.pdf | Bin 565816 -> 576617 bytes .../main/edited/seeds_and_ledgers_3.ly | 4 +- .../main/edited/seeds_and_ledgers_3.pdf | Bin 432251 -> 432879 bytes .../piece_ledger/314s49e1/lilypond/part_I.ly | 54 +- .../piece_ledger/314s49e1/lilypond/part_II.ly | 24 +- .../314s49e1/lilypond/part_III.ly | 42 +- .../piece_ledger/314s49e1/lilypond/part_IV.ly | 54 +- .../piece_ledger/4c01589b/lilypond/part_I.ly | 38 +- .../piece_ledger/4c01589b/lilypond/part_II.ly | 38 +- .../4c01589b/lilypond/part_III.ly | 36 +- .../piece_ledger/4c01589b/lilypond/part_IV.ly | 38 +- .../piece_ledger/7e170ef8/lilypond/part_I.ly | 34 +- .../piece_ledger/7e170ef8/lilypond/part_II.ly | 28 +- .../7e170ef8/lilypond/part_III.ly | 34 +- .../piece_ledger/7e170ef8/lilypond/part_IV.ly | 26 +- .../piece_ledger_pas.json | 27 - .../piece_ledger_pas.json_bak | 26 - .../314s49e1/314s49e1_code.scd | 581 ------- .../314s49e1/314s49e1_mus_model.json | 74 - .../449aeaa6/449aeaa6_code.scd | 907 ----------- .../449aeaa6/449aeaa6_mus_model.json | 83 - .../46210507/46210507_code.scd | 907 ----------- .../46210507/46210507_mus_model.json | 59 - .../4b96f62d/4b96f62d_code.scd | 907 ----------- .../4b96f62d/4b96f62d_mus_model.json | 48 - .../50fec831/50fec831_code.scd | 887 ----------- .../50fec831/50fec831_mus_model.json | 51 - .../5267b235/5267b235_code.scd | 887 ----------- .../5267b235/5267b235_mus_model.json | 43 - .../5625a95a/5625a95a_code.scd | 887 ----------- .../5625a95a/5625a95a_mus_model.json | 43 - .../628d5c8b/628d5c8b_code.scd | 741 --------- .../628d5c8b/628d5c8b_mus_model.json | 56 - .../6409252e/6409252e_code.scd | 907 ----------- .../6409252e/6409252e_mus_model.json | 49 - .../6a3f7c7c/6a3f7c7c_code.scd | 887 ----------- .../6a3f7c7c/6a3f7c7c_mus_model.json | 43 - .../6abf27d4/6abf27d4_code.scd | 808 ---------- .../6abf27d4/6abf27d4_mus_model.json | 93 -- .../6d0c2f19/6d0c2f19_code.scd | 887 ----------- .../6d0c2f19/6d0c2f19_mus_model.json | 44 - .../6d743c5c/6d743c5c_code.scd | 881 ----------- .../6d743c5c/6d743c5c_mus_model.json | 41 - .../6f1305ed/6f1305ed_code.scd | 894 ----------- .../6f1305ed/6f1305ed_mus_model.json | 51 - .../703e109b/703e109b_code.scd | 907 ----------- .../703e109b/703e109b_mus_model.json | 48 - .../74faf83f/74faf83f_code.scd | 907 ----------- .../74faf83f/74faf83f_mus_model.json | 83 - .../7ac10d34/7ac10d34_code.scd | 719 --------- .../7ac10d34/7ac10d34_gui_state.json | 1359 ----------------- .../7ac10d34/7ac10d34_mus_model.json | 59 - .../7bf874ce/7bf874ce_code.scd | 887 ----------- .../7bf874ce/7bf874ce_mus_model.json | 59 - .../7c7a96a2/7c7a96a2_code.scd | 897 ----------- .../7c7a96a2/7c7a96a2_mus_model.json | 45 - .../7c8bc6df/7c8bc6df_code.scd | 907 ----------- .../7c8bc6df/7c8bc6df_mus_model.json | 84 - .../7e170ef8/7e170ef8_code.scd | 718 --------- .../7e170ef8/7e170ef8_gui_state.json | 1359 ----------------- .../7e170ef8/7e170ef8_mus_model.json | 79 - .../7fd4d544/7fd4d544_code.scd | 894 ----------- .../7fd4d544/7fd4d544_mus_model.json | 44 - .../string_quartet_1.json | 25 - .../4200a90d/4200a90d_code.scd | 945 ------------ .../4200a90d/4200a90d_mus_model.json | 58 - .../4200a90d/lilypond/part_I.ly | 18 - .../4200a90d/lilypond/part_II.ly | 18 - .../4200a90d/lilypond/part_III.ly | 18 - .../4200a90d/lilypond/part_IV.ly | 18 - .../43b009ff/43b009ff_code.scd | 945 ------------ .../43b009ff/43b009ff_mus_model.json | 48 - .../43b009ff/lilypond/part_I.ly | 28 - .../43b009ff/lilypond/part_II.ly | 28 - .../43b009ff/lilypond/part_III.ly | 28 - .../43b009ff/lilypond/part_IV.ly | 28 - .../443ec222/443ec222_code.scd | 945 ------------ .../443ec222/443ec222_mus_model.json | 54 - .../443ec222/lilypond/part_I.ly | 18 - .../443ec222/lilypond/part_II.ly | 18 - .../443ec222/lilypond/part_III.ly | 18 - .../443ec222/lilypond/part_IV.ly | 18 - .../4526b76b/4526b76b_code.scd | 943 ------------ .../4526b76b/4526b76b_mus_model.json | 44 - .../46985d14/46985d14_code.scd | 1058 ------------- .../46985d14/46985d14_mus_model.json | 85 -- .../46985d14/lilypond/part_I.ly | 50 - .../46985d14/lilypond/part_II.ly | 50 - .../46985d14/lilypond/part_III.ly | 50 - .../46985d14/lilypond/part_IV.ly | 50 - .../490b1e6e/490b1e6e_code.scd | 1058 ------------- .../490b1e6e/490b1e6e_mus_model.json | 63 - .../490b1e6e/lilypond/part_I.ly | 26 - .../490b1e6e/lilypond/part_II.ly | 26 - .../490b1e6e/lilypond/part_III.ly | 26 - .../490b1e6e/lilypond/part_IV.ly | 26 - .../4a8a6e53/4a8a6e53_code.scd | 1058 ------------- .../4a8a6e53/4a8a6e53_mus_model.json | 97 -- .../4a8a6e53/lilypond/part_I.ly | 56 - .../4a8a6e53/lilypond/part_II.ly | 56 - .../4a8a6e53/lilypond/part_III.ly | 56 - .../4a8a6e53/lilypond/part_IV.ly | 56 - .../4b7745df/4b7745df_code.scd | 945 ------------ .../4b7745df/4b7745df_mus_model.json | 48 - .../4b7745df/lilypond/part_I.ly | 28 - .../4b7745df/lilypond/part_II.ly | 28 - .../4b7745df/lilypond/part_III.ly | 28 - .../4b7745df/lilypond/part_IV.ly | 28 - .../4e7d35e5/4e7d35e5_code.scd | 945 ------------ .../4e7d35e5/4e7d35e5_mus_model.json | 52 - .../4e7d35e5/lilypond/part_I.ly | 14 - .../4e7d35e5/lilypond/part_II.ly | 14 - .../4e7d35e5/lilypond/part_III.ly | 14 - .../4e7d35e5/lilypond/part_IV.ly | 14 - .../52c9a980/52c9a980_code.scd | 945 ------------ .../52c9a980/52c9a980_mus_model.json | 55 - .../52c9a980/lilypond/part_I.ly | 18 - .../52c9a980/lilypond/part_II.ly | 18 - .../52c9a980/lilypond/part_III.ly | 18 - .../52c9a980/lilypond/part_IV.ly | 18 - .../5e54c468/5e54c468_code.scd | 1058 ------------- .../5e54c468/5e54c468_mus_model.json | 70 - .../5e54c468/lilypond/part_I.ly | 44 - .../5e54c468/lilypond/part_II.ly | 44 - .../5e54c468/lilypond/part_III.ly | 44 - .../5e54c468/lilypond/part_IV.ly | 44 - .../61ce9067/61ce9067_code.scd | 945 ------------ .../61ce9067/61ce9067_mus_model.json | 55 - .../61ce9067/lilypond/part_I.ly | 10 - .../61ce9067/lilypond/part_II.ly | 10 - .../61ce9067/lilypond/part_III.ly | 10 - .../61ce9067/lilypond/part_IV.ly | 10 - .../62820081/62820081_code.scd | 945 ------------ .../62820081/62820081_mus_model.json | 48 - .../631e2af1/631e2af1_code.scd | 943 ------------ .../631e2af1/631e2af1_mus_model.json | 48 - .../66f6a618/66f6a618_code.scd | 1058 ------------- .../66f6a618/66f6a618_mus_model.json | 91 -- .../66f6a618/lilypond/part_I.ly | 70 - .../66f6a618/lilypond/part_II.ly | 70 - .../66f6a618/lilypond/part_III.ly | 70 - .../66f6a618/lilypond/part_IV.ly | 70 - .../6d635e88/6d635e88_code.scd | 945 ------------ .../6d635e88/6d635e88_mus_model.json | 95 -- .../6d635e88/lilypond/part_I.ly | 70 - .../6d635e88/lilypond/part_II.ly | 70 - .../6d635e88/lilypond/part_III.ly | 70 - .../6d635e88/lilypond/part_IV.ly | 70 - .../6ed95c4c/6ed95c4c_code.scd | 945 ------------ .../6ed95c4c/6ed95c4c_mus_model.json | 66 - .../6ed95c4c/lilypond/part_I.ly | 42 - .../6ed95c4c/lilypond/part_II.ly | 42 - .../6ed95c4c/lilypond/part_III.ly | 42 - .../6ed95c4c/lilypond/part_IV.ly | 42 - .../6fb60ab6/6fb60ab6_code.scd | 1058 ------------- .../6fb60ab6/6fb60ab6_mus_model.json | 56 - .../6fb60ab6/lilypond/part_I.ly | 28 - .../6fb60ab6/lilypond/part_II.ly | 28 - .../6fb60ab6/lilypond/part_III.ly | 28 - .../6fb60ab6/lilypond/part_IV.ly | 28 - .../761e4585/761e4585_code.scd | 1058 ------------- .../761e4585/761e4585_mus_model.json | 80 - .../761e4585/lilypond/part_I.ly | 36 - .../761e4585/lilypond/part_II.ly | 36 - .../761e4585/lilypond/part_III.ly | 36 - .../761e4585/lilypond/part_IV.ly | 36 - .../774ed940/774ed940_code.scd | 945 ------------ .../774ed940/774ed940_mus_model.json | 70 - .../774ed940/lilypond/part_I.ly | 22 - .../774ed940/lilypond/part_II.ly | 22 - .../774ed940/lilypond/part_III.ly | 22 - .../774ed940/lilypond/part_IV.ly | 22 - .../784130cc/784130cc_code.scd | 945 ------------ .../784130cc/784130cc_mus_model.json | 53 - .../784130cc/lilypond/part_I.ly | 14 - .../784130cc/lilypond/part_II.ly | 14 - .../784130cc/lilypond/part_III.ly | 14 - .../784130cc/lilypond/part_IV.ly | 14 - .../79e0a4a7/79e0a4a7_code.scd | 943 ------------ .../79e0a4a7/79e0a4a7_mus_model.json | 47 - .../79e0a4a7/lilypond/part_I.ly | 28 - .../79e0a4a7/lilypond/part_II.ly | 28 - .../79e0a4a7/lilypond/part_III.ly | 28 - .../79e0a4a7/lilypond/part_IV.ly | 28 - .../7d3c9a80/7d3c9a80_code.scd | 945 ------------ .../7d3c9a80/7d3c9a80_mus_model.json | 48 - .../7d3c9a80/lilypond/part_I.ly | 30 - .../7d3c9a80/lilypond/part_II.ly | 30 - .../7d3c9a80/lilypond/part_III.ly | 30 - .../7d3c9a80/lilypond/part_IV.ly | 30 - .../7edbdceb/7edbdceb_code.scd | 945 ------------ .../7edbdceb/7edbdceb_mus_model.json | 53 - .../7edbdceb/lilypond/part_I.ly | 14 - .../7edbdceb/lilypond/part_II.ly | 14 - .../7edbdceb/lilypond/part_III.ly | 14 - .../7edbdceb/lilypond/part_IV.ly | 14 - .../string_quartet_1/tmp/tmp_mus_model.json | 78 - .../string_quartet_2.json | 16 - .../string_quartet_2.json_bak | 15 - .../40119c5a/40119c5a_code.scd | 945 ------------ .../40119c5a/40119c5a_mus_model.json | 58 - .../41e447bc/41e447bc_code.scd | 945 ------------ .../41e447bc/41e447bc_mus_model.json | 64 - .../41e447bc/lilypond/part_I.ly | 20 - .../41e447bc/lilypond/part_II.ly | 20 - .../41e447bc/lilypond/part_III.ly | 20 - .../41e447bc/lilypond/part_IV.ly | 20 - .../42c3365b/42c3365b_code.scd | 945 ------------ .../42c3365b/42c3365b_mus_model.json | 123 -- .../4660b5c4/4660b5c4_code.scd | 945 ------------ .../4660b5c4/4660b5c4_mus_model.json | 59 - .../4a8a6e53/4a8a6e53_code.scd | 1058 ------------- .../4a8a6e53/4a8a6e53_mus_model.json | 97 -- .../4a8a6e53/lilypond/part_I.ly | 56 - .../4a8a6e53/lilypond/part_II.ly | 56 - .../4a8a6e53/lilypond/part_III.ly | 56 - .../4a8a6e53/lilypond/part_IV.ly | 56 - .../4c059f33/4c059f33_code.scd | 945 ------------ .../4c059f33/4c059f33_mus_model.json | 58 - .../4c059f33/lilypond/part_I.ly | 16 - .../4c059f33/lilypond/part_II.ly | 16 - .../4c059f33/lilypond/part_III.ly | 16 - .../4c059f33/lilypond/part_IV.ly | 16 - .../5201b8af/5201b8af_code.scd | 945 ------------ .../5201b8af/5201b8af_mus_model.json | 58 - .../5201b8af/lilypond/part_I.ly | 16 - .../5201b8af/lilypond/part_II.ly | 16 - .../5201b8af/lilypond/part_III.ly | 16 - .../5201b8af/lilypond/part_IV.ly | 16 - .../525274f2/525274f2_code.scd | 945 ------------ .../525274f2/525274f2_mus_model.json | 66 - .../525274f2/lilypond/part_I.ly | 14 - .../525274f2/lilypond/part_II.ly | 14 - .../525274f2/lilypond/part_III.ly | 14 - .../525274f2/lilypond/part_IV.ly | 14 - .../60adbbef/60adbbef_code.scd | 945 ------------ .../60adbbef/60adbbef_mus_model.json | 65 - .../60adbbef/lilypond/part_I.ly | 38 - .../60adbbef/lilypond/part_II.ly | 38 - .../60adbbef/lilypond/part_III.ly | 38 - .../60adbbef/lilypond/part_IV.ly | 38 - .../61e92979/61e92979_code.scd | 945 ------------ .../61e92979/61e92979_mus_model.json | 67 - .../62300302/62300302_code.scd | 945 ------------ .../62300302/62300302_mus_model.json | 77 - .../62300302/lilypond/part_I.ly | 36 - .../62300302/lilypond/part_II.ly | 36 - .../62300302/lilypond/part_III.ly | 36 - .../62300302/lilypond/part_IV.ly | 36 - .../628706ec/628706ec_code.scd | 945 ------------ .../628706ec/628706ec_mus_model.json | 117 -- .../628706ec/lilypond/part_I.ly | 46 - .../628706ec/lilypond/part_II.ly | 46 - .../628706ec/lilypond/part_III.ly | 46 - .../628706ec/lilypond/part_IV.ly | 46 - .../63bf7942/63bf7942_code.scd | 945 ------------ .../63bf7942/63bf7942_mus_model.json | 67 - .../6a7a8dd9/6a7a8dd9_code.scd | 945 ------------ .../6a7a8dd9/6a7a8dd9_mus_model.json | 126 -- .../71add9fc/71add9fc_code.scd | 945 ------------ .../71add9fc/71add9fc_mus_model.json | 210 --- .../72dc057f/72dc057f_code.scd | 945 ------------ .../72dc057f/72dc057f_mus_model.json | 59 - .../72dc057f/lilypond/part_I.ly | 30 - .../72dc057f/lilypond/part_II.ly | 30 - .../72dc057f/lilypond/part_III.ly | 30 - .../72dc057f/lilypond/part_IV.ly | 30 - .../74307bb4/74307bb4_code.scd | 945 ------------ .../74307bb4/74307bb4_mus_model.json | 120 -- .../74307bb4/lilypond/part_I.ly | 142 -- .../74307bb4/lilypond/part_II.ly | 142 -- .../74307bb4/lilypond/part_III.ly | 142 -- .../74307bb4/lilypond/part_IV.ly | 142 -- .../74b8f8d9/74b8f8d9_code.scd | 945 ------------ .../74b8f8d9/74b8f8d9_mus_model.json | 77 - .../74b8f8d9/lilypond/part_I.ly | 50 - .../74b8f8d9/lilypond/part_II.ly | 50 - .../74b8f8d9/lilypond/part_III.ly | 50 - .../74b8f8d9/lilypond/part_IV.ly | 50 - .../76e45e56/76e45e56_code.scd | 945 ------------ .../76e45e56/76e45e56_mus_model.json | 71 - .../76e45e56/lilypond/part_I.ly | 38 - .../76e45e56/lilypond/part_II.ly | 38 - .../76e45e56/lilypond/part_III.ly | 38 - .../76e45e56/lilypond/part_IV.ly | 38 - .../77b0d2dc/77b0d2dc_code.scd | 945 ------------ .../77b0d2dc/77b0d2dc_mus_model.json | 59 - .../7bb0e931/7bb0e931_code.scd | 945 ------------ .../7bb0e931/7bb0e931_mus_model.json | 69 - .../7df3df4c/7df3df4c_code.scd | 945 ------------ .../7df3df4c/7df3df4c_mus_model.json | 59 - .../7fe1da13/7fe1da13_code.scd | 945 ------------ .../7fe1da13/7fe1da13_mus_model.json | 198 --- .../string_quartet_2/tmp/tmp_mus_model.json | 71 - .../string_quartet_3.json | 21 - .../string_quartet_3.json_bak | 20 - .../45fa07e8/45fa07e8_code.scd | 966 ------------ .../45fa07e8/45fa07e8_mus_model.json | 443 ------ .../4ff624b0/4ff624b0_code.scd | 975 ------------ .../4ff624b0/4ff624b0_mus_model.json | 552 ------- .../5201b8af/5201b8af_code.scd | 945 ------------ .../5201b8af/5201b8af_mus_model.json | 58 - .../5201b8af/lilypond/part_I.ly | 16 - .../5201b8af/lilypond/part_II.ly | 16 - .../5201b8af/lilypond/part_III.ly | 16 - .../5201b8af/lilypond/part_IV.ly | 16 - .../5488f7e9/5488f7e9_code.scd | 945 ------------ .../5488f7e9/5488f7e9_mus_model.json | 163 -- .../55bd25a1/55bd25a1_code.scd | 973 ------------ .../55bd25a1/55bd25a1_mus_model.json | 548 ------- .../55f9b81e/55f9b81e_code.scd | 958 ------------ .../55f9b81e/55f9b81e_mus_model.json | 443 ------ .../577cf188/577cf188_code.scd | 945 ------------ .../577cf188/577cf188_mus_model.json | 198 --- .../5ec14635/5ec14635_code.scd | 946 ------------ .../5ec14635/5ec14635_mus_model.json | 163 -- .../69c568c6/69c568c6_code.scd | 973 ------------ .../69c568c6/69c568c6_mus_model.json | 535 ------- .../6a9928d6/6a9928d6_code.scd | 973 ------------ .../6a9928d6/6a9928d6_mus_model.json | 554 ------- .../6f0f638f/6f0f638f_code.scd | 945 ------------ .../6f0f638f/6f0f638f_mus_model.json | 105 -- .../726a40c7/726a40c7_code.scd | 946 ------------ .../726a40c7/726a40c7_mus_model.json | 163 -- .../75316bf0/75316bf0_code.scd | 973 ------------ .../75316bf0/75316bf0_mus_model.json | 550 ------- .../781442dc/781442dc_code.scd | 945 ------------ .../781442dc/781442dc_mus_model.json | 117 -- .../7c2de94c/7c2de94c_code.scd | 945 ------------ .../7c2de94c/7c2de94c_mus_model.json | 163 -- .../7e230015/7e230015_code.scd | 975 ------------ .../7e230015/7e230015_mus_model.json | 532 ------- .../string_quartet_3/tmp/tmp_mus_model.json | 532 ------- .../string_quartet_3_rise.json | 21 - .../string_quartet_3_rise.json_bak | 20 - .../43214be8/43214be8_code.scd | 981 ------------ .../43214be8/43214be8_mus_model.json | 158 -- .../43214be8/lilypond/part_I.ly | 48 - .../43214be8/lilypond/part_II.ly | 48 - .../43214be8/lilypond/part_III.ly | 48 - .../43214be8/lilypond/part_IV.ly | 48 - .../44490863/44490863_code.scd | 981 ------------ .../44490863/44490863_mus_model.json | 154 -- .../44490863/lilypond/part_I.ly | 48 - .../44490863/lilypond/part_II.ly | 48 - .../44490863/lilypond/part_III.ly | 48 - .../44490863/lilypond/part_IV.ly | 48 - .../4874dd07/4874dd07_code.scd | 979 ------------ .../4874dd07/4874dd07_mus_model.json | 121 -- .../4874dd07/lilypond/part_I.ly | 38 - .../4874dd07/lilypond/part_II.ly | 38 - .../4874dd07/lilypond/part_III.ly | 38 - .../4874dd07/lilypond/part_IV.ly | 38 - .../4b40ed47/4b40ed47_code.scd | 981 ------------ .../4b40ed47/4b40ed47_mus_model.json | 86 -- .../4b40ed47/lilypond/part_I.ly | 22 - .../4b40ed47/lilypond/part_II.ly | 22 - .../4b40ed47/lilypond/part_III.ly | 22 - .../4b40ed47/lilypond/part_IV.ly | 22 - .../4bf1af12/4bf1af12_code.scd | 981 ------------ .../4bf1af12/4bf1af12_mus_model.json | 87 -- .../4bf1af12/lilypond/part_I.ly | 22 - .../4bf1af12/lilypond/part_II.ly | 22 - .../4bf1af12/lilypond/part_III.ly | 22 - .../4bf1af12/lilypond/part_IV.ly | 22 - .../4c745666/4c745666_code.scd | 977 ------------ .../4c745666/4c745666_mus_model.json | 166 -- .../4e9f1dcc/4e9f1dcc_code.scd | 981 ------------ .../4e9f1dcc/4e9f1dcc_mus_model.json | 86 -- .../4e9f1dcc/lilypond/part_I.ly | 22 - .../4e9f1dcc/lilypond/part_II.ly | 22 - .../4e9f1dcc/lilypond/part_III.ly | 22 - .../4e9f1dcc/lilypond/part_IV.ly | 22 - .../4ef018fc/4ef018fc_code.scd | 945 ------------ .../4ef018fc/4ef018fc_mus_model.json | 79 - .../4ef018fc/lilypond/part_I.ly | 26 - .../4ef018fc/lilypond/part_II.ly | 26 - .../4ef018fc/lilypond/part_III.ly | 26 - .../4ef018fc/lilypond/part_IV.ly | 26 - .../521654f8/521654f8_code.scd | 981 ------------ .../521654f8/521654f8_mus_model.json | 87 -- .../521654f8/lilypond/part_I.ly | 22 - .../521654f8/lilypond/part_II.ly | 22 - .../521654f8/lilypond/part_III.ly | 22 - .../521654f8/lilypond/part_IV.ly | 22 - .../531df78c/531df78c_code.scd | 981 ------------ .../531df78c/531df78c_mus_model.json | 157 -- .../531df78c/lilypond/part_I.ly | 48 - .../531df78c/lilypond/part_II.ly | 48 - .../531df78c/lilypond/part_III.ly | 48 - .../531df78c/lilypond/part_IV.ly | 48 - .../553fbac7/553fbac7_code.scd | 979 ------------ .../553fbac7/553fbac7_mus_model.json | 88 -- .../57ef90e6/57ef90e6_code.scd | 975 ------------ .../57ef90e6/57ef90e6_mus_model.json | 166 -- .../615c4008/615c4008_code.scd | 992 ------------ .../615c4008/615c4008_mus_model.json | 267 ---- .../6522664c/6522664c_code.scd | 981 ------------ .../6522664c/6522664c_mus_model.json | 85 -- .../6522664c/lilypond/part_I.ly | 20 - .../6522664c/lilypond/part_II.ly | 20 - .../6522664c/lilypond/part_III.ly | 20 - .../6522664c/lilypond/part_IV.ly | 20 - .../6db2efcc/6db2efcc_code.scd | 981 ------------ .../6db2efcc/6db2efcc_mus_model.json | 86 -- .../6db2efcc/lilypond/part_I.ly | 22 - .../6db2efcc/lilypond/part_II.ly | 22 - .../6db2efcc/lilypond/part_III.ly | 22 - .../6db2efcc/lilypond/part_IV.ly | 22 - .../7276dc78/7276dc78_code.scd | 981 ------------ .../7276dc78/7276dc78_mus_model.json | 158 -- .../7276dc78/lilypond/part_I.ly | 48 - .../7276dc78/lilypond/part_II.ly | 48 - .../7276dc78/lilypond/part_III.ly | 48 - .../7276dc78/lilypond/part_IV.ly | 48 - .../78a94ed1/78a94ed1_code.scd | 981 ------------ .../78a94ed1/78a94ed1_mus_model.json | 90 -- .../78a94ed1/lilypond/part_I.ly | 26 - .../78a94ed1/lilypond/part_II.ly | 26 - .../78a94ed1/lilypond/part_III.ly | 26 - .../78a94ed1/lilypond/part_IV.ly | 26 - .../7c30c182/7c30c182_code.scd | 981 ------------ .../7c30c182/7c30c182_mus_model.json | 271 ---- .../7c30c182/lilypond/part_I.ly | 92 -- .../7c30c182/lilypond/part_II.ly | 92 -- .../7c30c182/lilypond/part_III.ly | 92 -- .../7c30c182/lilypond/part_IV.ly | 92 -- .../7ede7adb/7ede7adb_code.scd | 981 ------------ .../7ede7adb/7ede7adb_mus_model.json | 83 - .../7ede7adb/lilypond/part_I.ly | 18 - .../7ede7adb/lilypond/part_II.ly | 18 - .../7ede7adb/lilypond/part_III.ly | 18 - .../7ede7adb/lilypond/part_IV.ly | 18 - .../tmp/tmp_mus_model.json | 274 ---- .../60adbbef/lilypond/part_I.ly | 8 +- .../60adbbef/lilypond/part_II.ly | 6 - .../60adbbef/lilypond/part_III.ly | 6 - .../60adbbef/lilypond/part_IV.ly | 6 - .../74b8f8d9/lilypond/part_I.ly | 8 +- .../74b8f8d9/lilypond/part_II.ly | 6 - .../74b8f8d9/lilypond/part_III.ly | 6 - .../74b8f8d9/lilypond/part_IV.ly | 6 - .../string_quartet_3_rise_coda_only.json | 3 +- .../4dd2a130/4dd2a130_mus_model.json | 34 +- .../4dd2a130/lilypond/part_II.ly | 4 +- .../4dd2a130/lilypond/part_IV.ly | 4 +- .../50c2b0ad/50c2b0ad_mus_model.json | 40 +- .../50c2b0ad/lilypond/part_III.ly | 4 +- .../50c2b0ad/lilypond/part_IV.ly | 4 +- .../536cac90/536cac90_mus_model.json | 23 +- .../536cac90/lilypond/part_I.ly | 10 +- .../536cac90/lilypond/part_II.ly | 8 +- .../536cac90/lilypond/part_III.ly | 8 +- .../536cac90/lilypond/part_IV.ly | 8 +- .../5ededd80/5ededd80_mus_model.json | 16 +- .../5ededd80/lilypond/part_I.ly | 8 +- .../5ededd80/lilypond/part_II.ly | 8 +- .../5ededd80/lilypond/part_III.ly | 8 +- .../5ededd80/lilypond/part_IV.ly | 8 +- .../5ef20586/5ef20586_mus_model.json | 8 +- .../5ef20586/lilypond/part_II.ly | 2 +- .../5f0075ab/5f0075ab_mus_model.json | 2 +- .../5f0075ab/lilypond/part_IV.ly | 2 +- .../61207e49/61207e49_mus_model.json | 54 +- .../61207e49/lilypond/part_I.ly | 4 +- .../61207e49/lilypond/part_II.ly | 6 +- .../61207e49/lilypond/part_III.ly | 4 +- .../624f7439/624f7439_mus_model.json | 70 +- .../624f7439/lilypond/part_I.ly | 4 +- .../624f7439/lilypond/part_II.ly | 2 +- .../624f7439/lilypond/part_IV.ly | 4 +- .../65120e88/65120e88_mus_model.json | 12 +- .../65120e88/lilypond/part_III.ly | 4 +- .../66b20499/66b20499_mus_model.json | 30 +- .../66b20499/lilypond/part_IV.ly | 4 +- .../736745da/736745da_mus_model.json | 4 +- .../736745da/lilypond/part_II.ly | 2 +- .../767e70f0/767e70f0_mus_model.json | 32 +- .../767e70f0/lilypond/part_IV.ly | 4 +- 486 files changed, 472 insertions(+), 121760 deletions(-) delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas.json_bak delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/314s49e1/314s49e1_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/314s49e1/314s49e1_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/449aeaa6/449aeaa6_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/449aeaa6/449aeaa6_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/46210507/46210507_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/46210507/46210507_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/4b96f62d/4b96f62d_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/4b96f62d/4b96f62d_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/50fec831/50fec831_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/50fec831/50fec831_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/5267b235/5267b235_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/5267b235/5267b235_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/5625a95a/5625a95a_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/5625a95a/5625a95a_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/628d5c8b/628d5c8b_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/628d5c8b/628d5c8b_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/6409252e/6409252e_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/6409252e/6409252e_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/6a3f7c7c/6a3f7c7c_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/6a3f7c7c/6a3f7c7c_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/6abf27d4/6abf27d4_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/6abf27d4/6abf27d4_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/6d0c2f19/6d0c2f19_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/6d0c2f19/6d0c2f19_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/6d743c5c/6d743c5c_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/6d743c5c/6d743c5c_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/6f1305ed/6f1305ed_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/6f1305ed/6f1305ed_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/703e109b/703e109b_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/703e109b/703e109b_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/74faf83f/74faf83f_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/74faf83f/74faf83f_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/7ac10d34/7ac10d34_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/7ac10d34/7ac10d34_gui_state.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/7ac10d34/7ac10d34_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/7bf874ce/7bf874ce_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/7bf874ce/7bf874ce_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/7c7a96a2/7c7a96a2_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/7c7a96a2/7c7a96a2_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/7c8bc6df/7c8bc6df_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/7c8bc6df/7c8bc6df_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/7e170ef8/7e170ef8_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/7e170ef8/7e170ef8_gui_state.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/7e170ef8/7e170ef8_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/7fd4d544/7fd4d544_code.scd delete mode 100644 resources/resources_bak_2024_01_03/piece_ledger_pas/7fd4d544/7fd4d544_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/4200a90d_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/4200a90d_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/43b009ff_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/43b009ff_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/443ec222/443ec222_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/443ec222/443ec222_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/443ec222/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/443ec222/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/443ec222/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/443ec222/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4526b76b/4526b76b_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4526b76b/4526b76b_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/46985d14/46985d14_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/46985d14/46985d14_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/46985d14/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/46985d14/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/46985d14/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/46985d14/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/490b1e6e_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/490b1e6e_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/4a8a6e53_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/4a8a6e53_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/4b7745df_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/4b7745df_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/4e7d35e5_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/4e7d35e5_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/52c9a980_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/52c9a980_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/5e54c468_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/5e54c468_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/61ce9067_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/61ce9067_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/62820081/62820081_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/62820081/62820081_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/631e2af1/631e2af1_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/631e2af1/631e2af1_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/66f6a618_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/66f6a618_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/6d635e88_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/6d635e88_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/6ed95c4c_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/6ed95c4c_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/6fb60ab6_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/6fb60ab6_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/761e4585/761e4585_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/761e4585/761e4585_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/761e4585/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/761e4585/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/761e4585/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/761e4585/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/774ed940/774ed940_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/774ed940/774ed940_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/774ed940/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/774ed940/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/774ed940/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/774ed940/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/784130cc/784130cc_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/784130cc/784130cc_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/784130cc/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/784130cc/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/784130cc/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/784130cc/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/79e0a4a7_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/79e0a4a7_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/7d3c9a80_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/7d3c9a80_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/7edbdceb_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/7edbdceb_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_1/tmp/tmp_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2.json_bak delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/40119c5a/40119c5a_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/40119c5a/40119c5a_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/41e447bc_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/41e447bc_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/42c3365b/42c3365b_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/42c3365b/42c3365b_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/4660b5c4/4660b5c4_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/4660b5c4/4660b5c4_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/4a8a6e53_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/4a8a6e53_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/4c059f33_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/4c059f33_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/5201b8af_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/5201b8af_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/525274f2/525274f2_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/525274f2/525274f2_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/525274f2/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/525274f2/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/525274f2/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/525274f2/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/60adbbef_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/60adbbef_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/61e92979/61e92979_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/61e92979/61e92979_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/62300302/62300302_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/62300302/62300302_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/62300302/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/62300302/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/62300302/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/62300302/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/628706ec/628706ec_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/628706ec/628706ec_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/628706ec/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/628706ec/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/628706ec/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/628706ec/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/63bf7942/63bf7942_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/63bf7942/63bf7942_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/6a7a8dd9/6a7a8dd9_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/6a7a8dd9/6a7a8dd9_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/71add9fc/71add9fc_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/71add9fc/71add9fc_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/72dc057f_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/72dc057f_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/74307bb4_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/74307bb4_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/74b8f8d9_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/74b8f8d9_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/76e45e56_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/76e45e56_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/77b0d2dc/77b0d2dc_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/77b0d2dc/77b0d2dc_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/7bb0e931/7bb0e931_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/7bb0e931/7bb0e931_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/7df3df4c/7df3df4c_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/7df3df4c/7df3df4c_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/7fe1da13/7fe1da13_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/7fe1da13/7fe1da13_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_2/tmp/tmp_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3.json_bak delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/45fa07e8/45fa07e8_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/45fa07e8/45fa07e8_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/4ff624b0/4ff624b0_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/4ff624b0/4ff624b0_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/5201b8af_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/5201b8af_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/5488f7e9/5488f7e9_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/5488f7e9/5488f7e9_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/55bd25a1/55bd25a1_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/55bd25a1/55bd25a1_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/55f9b81e/55f9b81e_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/55f9b81e/55f9b81e_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/577cf188/577cf188_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/577cf188/577cf188_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/5ec14635/5ec14635_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/5ec14635/5ec14635_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/69c568c6/69c568c6_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/69c568c6/69c568c6_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/6a9928d6/6a9928d6_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/6a9928d6/6a9928d6_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/6f0f638f/6f0f638f_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/6f0f638f/6f0f638f_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/726a40c7/726a40c7_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/726a40c7/726a40c7_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/75316bf0/75316bf0_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/75316bf0/75316bf0_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/781442dc/781442dc_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/781442dc/781442dc_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/7c2de94c/7c2de94c_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/7c2de94c/7c2de94c_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/7e230015/7e230015_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/7e230015/7e230015_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3/tmp/tmp_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise.json_bak delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/43214be8_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/43214be8_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/44490863_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/44490863_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/4874dd07_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/4874dd07_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/4b40ed47_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/4b40ed47_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/4bf1af12_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/4bf1af12_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4c745666/4c745666_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4c745666/4c745666_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/4e9f1dcc_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/4e9f1dcc_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/4ef018fc_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/4ef018fc_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/521654f8_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/521654f8_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/531df78c_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/531df78c_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/553fbac7/553fbac7_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/553fbac7/553fbac7_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/57ef90e6/57ef90e6_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/57ef90e6/57ef90e6_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/615c4008/615c4008_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/615c4008/615c4008_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/6522664c_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/6522664c_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/6db2efcc_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/6db2efcc_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/7276dc78_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/7276dc78_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/78a94ed1_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/78a94ed1_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/7c30c182_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/7c30c182_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/7ede7adb_code.scd delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/7ede7adb_mus_model.json delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/lilypond/part_I.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/lilypond/part_II.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/lilypond/part_III.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/lilypond/part_IV.ly delete mode 100644 resources/resources_bak_2024_01_03/string_quartet_3_rise/tmp/tmp_mus_model.json diff --git a/lilypond/includes/part_I.ly b/lilypond/includes/part_I.ly index fad68f5..118203a 100644 --- a/lilypond/includes/part_I.ly +++ b/lilypond/includes/part_I.ly @@ -11,3 +11,4 @@ \include "/home/mwinter/Sketches/seeds_and_ledgers/source/resources/string_quartet_3_rise_coda_only/4dd2a130/lilypond/part_I.ly" \include "/home/mwinter/Sketches/seeds_and_ledgers/source/resources/string_quartet_3_rise_coda_only/767e70f0/lilypond/part_I.ly" \include "/home/mwinter/Sketches/seeds_and_ledgers/source/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_I.ly" +\include "/home/mwinter/Sketches/seeds_and_ledgers/source/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_I.ly" diff --git a/lilypond/includes/part_II.ly b/lilypond/includes/part_II.ly index 1a93ad0..c059a30 100644 --- a/lilypond/includes/part_II.ly +++ b/lilypond/includes/part_II.ly @@ -11,3 +11,4 @@ \include "/home/mwinter/Sketches/seeds_and_ledgers/source/resources/string_quartet_3_rise_coda_only/4dd2a130/lilypond/part_II.ly" \include "/home/mwinter/Sketches/seeds_and_ledgers/source/resources/string_quartet_3_rise_coda_only/767e70f0/lilypond/part_II.ly" \include "/home/mwinter/Sketches/seeds_and_ledgers/source/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_II.ly" +\include "/home/mwinter/Sketches/seeds_and_ledgers/source/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_II.ly" diff --git a/lilypond/includes/part_III.ly b/lilypond/includes/part_III.ly index 9d3d7c1..69d3434 100644 --- a/lilypond/includes/part_III.ly +++ b/lilypond/includes/part_III.ly @@ -11,3 +11,4 @@ \include "/home/mwinter/Sketches/seeds_and_ledgers/source/resources/string_quartet_3_rise_coda_only/4dd2a130/lilypond/part_III.ly" \include "/home/mwinter/Sketches/seeds_and_ledgers/source/resources/string_quartet_3_rise_coda_only/767e70f0/lilypond/part_III.ly" \include "/home/mwinter/Sketches/seeds_and_ledgers/source/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_III.ly" +\include "/home/mwinter/Sketches/seeds_and_ledgers/source/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_III.ly" diff --git a/lilypond/includes/part_IV.ly b/lilypond/includes/part_IV.ly index c138422..1592c57 100644 --- a/lilypond/includes/part_IV.ly +++ b/lilypond/includes/part_IV.ly @@ -11,3 +11,4 @@ \include "/home/mwinter/Sketches/seeds_and_ledgers/source/resources/string_quartet_3_rise_coda_only/4dd2a130/lilypond/part_IV.ly" \include "/home/mwinter/Sketches/seeds_and_ledgers/source/resources/string_quartet_3_rise_coda_only/767e70f0/lilypond/part_IV.ly" \include "/home/mwinter/Sketches/seeds_and_ledgers/source/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_IV.ly" +\include "/home/mwinter/Sketches/seeds_and_ledgers/source/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_IV.ly" diff --git a/lilypond/score_template.pdf b/lilypond/score_template.pdf index a14634b2d39d827b7396229dc5e7d749ab37625c..c6d05a2486cea65527920d8d58b37df811c925f1 100644 GIT binary patch delta 87353 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�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 delta 87575 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%0D^Ed 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 z�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 literal 922670 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�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%0A!MtJI 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 z zdkl|?l3)*PL`FsV0?4VGvWoiZ*>7D<{0oWX$j1IRf-OR%3nayAB5|pi*IRPx=IT=& zCgs}g$P+I1q9bu)jUfRS7&;L_N&c(7YL=WvsH-q=u@m}+FeXH2po}-#1(u^`lsWmX z>VKM`;ss4?D1-J!PVG;su$lKOda~S@0I8R5q#8A(Oo^DdUD8c+e8=pCvvgwrT@s$> z*#bpz4w&2+Xvva8VV#t>W~YSXVF+BdJ|&9m+y!6!GBKl2k7_UuABsUck>3vpxD!=m zzeLa$kNU%r-W6h{86H~W1b29wpVsgVWu^(bss=95#7Tu(+%++Qs+Idm6YF*9$Nq)s zf$+US5f91p^xIhE@<`>Z$nvkTNbw?;X0mC=;g3hwe?&bxkm1|Wq7kE_Pb%6AUh+NK z3BR-@+*ATkyY+Dm_c!86GVB!SlSOvwLXbo(KSmX=^gzL%B>su5^-@U&zN4x=da8qk zn^UsU)PI{cl8lz>QeY34sQ-rc=kq2_oP-Pa(=WQER$ zwXG@3j@;(1LX@q%o72G_SILa$hw#q@%zC;#{<*+q#NJ377xa>a^H0v+a@juGANb^P z6t?ii%&2rsk?)Z63vO$fiZY)VrXXxb;uCP-fe}%w(Nej?sTfv;dKnZ~+GjCDehn0e8$ebkXSeSuT@1 z+!7(->9jYjsbNx~DCA=QDswm40-u=t9Zie?bjGpA&)w9&vbuJm*h8L=&-HRfFkI1) zyT6-!KYHenTAtdtJwTWZSi-xibULVQlvs7p5UoX{@DvC)2ynIi!JkWoq>Q@T-9EPa zXWWEMdl>htolS_CI^TknO4hcAEDE=Qk5js?CuhdhqeI)9X79>gLQVqF9{-3Gc_o>Y z;OpHc&EBbD!j`xWzb#*K?#fX6rH@MwJQ^jZ*zQltycE)=Uj}%wr=`&~d2v#1UM_xp z=0xp_KLUD3D!q}>C4$-5#>ICjiI0c#lA4>#7x`*}MnL47kN057y7-&7$jp4d5Cv_i zxfL_%$qpdB#nqv51vCq5oC(L$p^NGZ0bbAP$}cQVqSa)v~30I>HKUp6FH7IfS3fd?T;9j)`Z{_wL#~ z!xkdha$)>TB?&*mqQ-I*(zhGG4&G=K9Wgb0nf@3Jsb_-sb7wht-7*yxk^Rcib*Os{?v z4;D|Yq+r29Wi=Fi5@HAs%MFam*|?kutX?(Z1CrE?oJ{_lcgQxz-678cInTp zgYRpVr+$*&95md_sPj(f$Z5;>#PlGw^DBE?KYS<6+ZEwQ>VCbWiET5iX=~IoW*DoI z;$tRgfghTc8c7(P8%3g+R5uy?br~#XozP5BAXF3|ez?~)ts39QH0z{-!tlWlK|YiH ziy6fIY!isxo6}OjmU;~u>)FVBJCsIFsyPi%C9j{0i2Lppu-}Zg;khpwbH;z$o0VO3 z+3IC5CDdlf!h)}`>g8%hFP-O!I@2`4z<2tM6QfCNJZx(stuR%exd^xjI_2&rLAV;2 zXrw+P2FV^nq@xYJf94E?c(JYaG+0m)F&6G>+91l#W*kInUQvLHIEJpG;>(@?oyWVT z#KfzQJQFHv>+6Dj@(-5LHwX{UhSVz_mCiE5;Hfzw9%iqP{0e$>dZL`t2f}mj);yA? z16u<@#XH1?6x6=n6@HS8KMgPWGJs`bSQk!E-w*jXZvs&C(UKHg%zlG0>{0Er)>%2QkQFYl$e%178kAj&jU26@X4U33HD3bsjHHF^ zZfbjz`y2)iH@a;U1z-ae+?~tth$Wg6%jtOiEvjRm_94ObQ|x0y-q*t^+@M#Nh8|^I zUMLD$=|`xOow4LFX*^j1@nAnIxMt7WJXZxe-SC@-2Cw>PMm)F>TUBs{i%Q{Lcs+#` z?K0Wz2+ZdRLc0+D1(XB1-`vFj|7rL-@UUH~dNUj{t61fk4ICaHVwpbFXb)a1LCHA? z7Qm3?S70+$YIJOsPD8IuOfKqwss@;&)-&}JX z!d!BQY2wBPEspX|>pA-7u;|19LT>ziRk79N+hr^HzIO==k!jfH$@yRCl(rSxjEM3K z1<})WV(qzAkd_Hv@<{r}$EefFXULNPF=&F8SWOL;JRVMT8^(t%Psx5(A zGNtW&9JQy<%M|6_Ond##Fg-UruBLOnSQK+jxKayLObi;;HEEA%G6D^pMN)%+bewOL zi|3q}4bClviS~>q!^kR2{hM;HbzYSR!lH1BMeJT?;;fWa>>AwTh7#PZkRc8;*Eq`-|)XphX9h|#igCLmFXX%)r_ zm!FUDoH=+T6Rf+wb(2BE*9LbRB zDn1nWtLVFqao-g92?A2SB2#!LIg7yCSvmcQ)5k93%L`=Zd9oR6$3+>K53>m}G2S?6iAo||Mhu%pF zRp52&%%?DPVSv^X=y}62L(0_q+X`R*Fnh}X4*D9| z;(mM(P}SHnL|DYAjfPxZfP6`ajb9XZXjC2TOCImmAb?ll-FJj?0LIb$H^}i&^I9Ho zYY5lk#`=X%8pZzc&u5)lx6>^FKcv&TWShRLD~8;>&{jI`B~{30;pJj`+c|$rygd9i z6Q?%N$iM%rJvd(aMQe_mQJ+RU*!=%6_Kwk+1Z}tQgcIYA?PMmllL_wFwr$(CHL-2m zwrx#p`{a4v_k4fOpYKmscduH#y85c>uHM()yKc3M%)d6k@bRH?4SFU5BqQs2m-;Yv zCx{JPvDqcoxSJ(!!AxlXB;LDdzdSk6Owr7jyo%rPkB=PuraVbk!=<6hUhQB$`%zhx$*@tQmt9&-4{pQbNqVjC^}IcuQc&A1?;JwzN} z!Er_@X79F1P`UTz3>N0Vg+bb~t7?^5w>Y}2~qwxD>H zttD}crl*e1{j*QA8&g2x%0H}Sn<1s)iJ8TgLmiXsQuwQgivYc6PGcAPeLdw15l4j` zU}SChzeW$=d;c+q_>U#Te@X^cc2*{s|2@gV&hh_vN3d|v|Nn81*z}U9Ci`}exM_^J zIM=B)IZ4p1PRt_vc8}nvWwi6$4NH(4w(37d*!j7mgZ4}pOz@D0uXJX1FFX^lRVY-e z2oRDZ9=syhYL0N|ghJC7>;H@mX!SdHq1# z-jc_Aux|RuQ}RSi@5B`R^Wpk-M)&oe&WLeX`EtwFeR84i@^P3wM)38%{`J~_wf#9x zu=VNx_wvf;O~z)o&T1<7$tU;eYniQ4!~y#4?efF>X7@vcYW2yL;qC2PZtTglmL75A zUzY5ssI23>D0di-Mpw9J#1@~z`fpEiT0-^^z^}A+x>-f*fm->*+Y%8WS(q<}fw%op zv`NO9S4K7_D`B-?PniN$wieR(&!Ie4O!>o(T7Rn8NZV$ z+Kb5?E|5JcmKGF?=aH4B)rjeRdA+Sr<}?BqYRRoJFn}scfZ3$R3IuH$TY30Q+aZz^X!uxJO{MJsDD{wS8_$57M6K=l0Z^-F$yLBVua7|_)mx0O#2a?%^QH? z2kKQ~K#|@59RL2wzgV7CMR5wX2w)IsL_C99j8Dod?Npa2kff%Fo;w9ppw4K{h1J&G zUhc|iE~m)mG>`wKgO&wN9}xZviNY$7+xlrGWj{Vm#FWV}gDK3pC&wt8rOqTz&c2q33S#SqCVP{$47~Zu+DWyFT4sFC_1Lo)yeAO;3CQ zU2Oi zd@fbg1=wKxzQ5h!QxV{DPCAO&XYSdFmyRk0EMtPT$wS{U%;BnZF7TT&9DXWc*jrKr2W=t;b1xEbJc!^_?IV8DF6h^Bk%~0S>!H^mDSAnEWqpc#Z zY=QNP79XWS(mGAB{V^+WTupsVGkufbkfPAk{Z#H;9H%p1c~JFFpf;cL+?J0hu{pt9 z=oIfj)g#ToZC%{N)dfej47R-0|UGpI-Hb}HAlP%JMvV_?o&vU%;MrLG%TdUari+3D=vo_mTlO} z*ty8o1kdG_v~av|)cFe>rHf)Nm~-c{uvw_B9O^QEMKh5$D^*7E8R_4M>^)H8H^_&R z!B;(TA~yqAwMhEP;<~32UO+5FfAJ8M+CMo_<;gB*_nDDs9mXtW_l1Q`WPUU#{u%&~ zY*HmApc&(OGp_0NCO{TiuQ{*Z8@>q5-Y>s|Y&(@b2!1Y{7|1VSs2OGbC`dAMbNShX zzILW^@zB5(ZAjjC|4PExX{~MyF<)aSp7twt5U!|OgYlxsLY`T@ovw*tOF2^PPpK8+ zm2>ws?*3`Fd|~E&Iomx%tNat^B@lb;qt1;L^0k`bqA(%6WfT_;?o$a9n%TBNHa;0^wVr<4xfx|c3!Q41J1P> z-;pe&O&)?u{e82?259{Uj%r`hjrf@NA5D~4qGsm^Vz24yXu!Xc^ zKW&mBj7gJJq>Fm3oyp+r@MVk)ch*tij{g$bS%mT$&iv$Bbyd4rtk0Wwn zAQv;tdMP2i5W&f48#k$>p-ku{0m>__%|9!Z6;HXWAV1;+N34$OdVHm@p|B02yK;HOBzFyUzu~P7&meg1JH$Rl!k=hc zczWSTbagj!rVle%@2h3KHGk)QxOnYeaIIb*i)e0!DdnXX8wZ6ErXWSoyS$65$gHUG zd9oi;V05;J;;(Ef!vkudqF-7)j85aGXQFK`bd$A=8i;iyZ>euE8~x#v={pHc;Sq9j zywM>@r_fQ~&FFUTq(T`zsnRC0BZh{!DCb0VacX?)3D$e#M8{&Xyu4U(ys8-*hnAab z1GP2JWY*pnD9py`eXSy7#&M>|Bik)!c9j7mbMm1@mi@lBC^Gq}*`Ll1~@0yuJDe=@`3Aa%&F4GhEbiq=$x zZ;U!bLHZ{vSE)pjgN8Rs$qbKcQsnw8_JmNn(C3pdRTd^JFs1T@#_tCEq_nwH$jt%D z&u1IntJE}7hN?4t>sg&cv5DBKWv>8grN(G|WK-_>yXz%t_3Q$g08^GDT&tv#?iBZb zki;j3MCB=3Q+@e)IloIb{+sVxl5F+GkYgvfVwQ`=?2EL~kuWcUBnDKZ~fvkqH*EC5y0bIJTIYszh=e6_7p*fXie3hX(X_D9X} zuBDWFP93I4*r3DOq<2|@Bo<o zpvp36fT-6|Y!a^Q?DP(H!3hf{ia(I@c0MIzmB+YKB5o);F z#$fb`O>Vevk;b*?Xtz@A`j3PLWUq;!!c{9yu9Ldhi8%y+FpqqQVB$c-zZ;6K$Yu6e z@!8Z6SBuo9v*xzFW;Oq0Ug=q7Ejv}N(8#W@AMY|}zX!zHUwxAN4P|}3J0<}(&r1Gm zuEd$6CQjrvq5sCkVcF-qhiY9p1`1fgbSI$(Rqs&g1&E%Y!fc4ovu%snICB~I7SCm4Z z7WiAX`4$3xz%Rg#8T(&vl~oUNV)Rx)&fUG{^tn8QU1$o7ZLo?3=CN=u1J6_SyL#Ju zaq~XT5Pgk(RWt8BBuWxk9`S*yO##>AOjc4Iy{tskcRZj;^A~al{jq0UlfQ@Mi|<21 zL*YaCQ-hFQTSMTMs73b_4TG%JgWB$2twrpO_^Ln+`O_KymTuUrm+vmMP4%apCV%_K zkud8B*q5?AoUK%{?|NaJwgl&P@3^a1IZJ0=YYj*5IF&lC+q9B7AWE85l4|vZxx!}o zu7kWgxQ@E$0wGYD$bU`nY@QgAz{=U+#v%2*P&obbVhLCtaQM|(I}!82RqyH*o;=fH z#`vbk(l@QQ!e%@o3`OfEAX-jThbFn^Fk_})j7|Da5V|pck)N=yeJ3?5r1>B33#nBr z*Yld5%lVd84|0`EZM;ff;)LD6V3Gx%XWgObk{!2i1Z)??VsDW`6)wy)aC8-s_(3+1 zMX@<#HZ&k)c2#FH9Qv^u# z&zj4fdVJujOXX>zZ{R4kTa7X{<$P#;0 z%%NmiE&*$poV2(G6g<1E$2ebuqVK1|IH$%!)F>olm5|& zHjd=QX|0!qN%gF`%zJ2kKc-tY!r* z4P99-h#;k5^M>_n?Ea|QH6=J>e8!|_sKneuK3%#O*Au#*Y6lZLJNL^&Lf)K{`wQSY zF`K{`bd#GeOXe01@pcJwtG|_Z7PSzsfJ;Kzp|WLMT9lZ>D=m|I?FL=5sza=8T4~Nc z8oWm71l>A#+8Jx=xQk_mWhE(IxzTiUS@d7#&&!ie&9QDca~Y`$4qO6v<(G}+h4GiC zAlq;uc;wQDnh$@exfrr&I<_eN7D}qj=#zaWKAvD$spU3_4&4sYzYHuE+17lL{S6)KGQYzd04RI2vY?; zq_1+Y8wYBVlsUi;4CF5GUS7^Ltb}q)DkX7;u0%unTt-)tfqEj?%56k z$1B@681+i0a=>!%F$6xlB}2Z>30~AbJD==uT7i2#RB<0+Ij=>OZ3Zdy%B? zh~vgwM!dL2gm?D)|Tj0Ent z*p%OEFC|!9J8f2cCQ{xYU|Hc>V!9v40q&8)bhwkv1pWz6B~Rag0!08f@Zhz>!)9v2erFTq<-yM-N4sV%+u<|} zfqikg(ZSaZwu#W)9#$AGil2F#Q-`EtqMSmo`~c)5_wK{vfP@DhUJ z<8Yrl6_PTN;v=-pOcHgrvhIEu%V?f!Y1`sX)i^+e-TLliIuqc~7>5}6zmi+s=E zkkHs~7hc)j`R@fm=Cre`U&ehOMml*(JKIhL$ zTf`EYgP*t}v0KtjJWs9XK=v#xp=oNJ{XXrH|xv~BCwFb+3J<{LNbu7 z(dMJP7jqIv1)plg;m*niS{Dn*i{N5$46VD2uU*)1aB zB044K8%q@bsV*Qo6(wZryO&|p3eKCJOF|iUoF<&ut&X&q^&6PvcA56b`D)ljz0g@L zA9jhN=*9LGyUBI~5Y%dyL2%lh^iRntv#L~VG$djzOdq@!4b9i1AGn4p>+6E@(^4zcExN6&mDCr7`t($|O^j!m?~ti8TsJ z>1~Sv#R@WgO3L#@tMhLNQzXf}sZ>>BK#`h-Oo{fS#D0x#Br6l^2MwF1xHcH(=>GRTA@)UY3OG+0>j9EjvIuS?XHts_5HAEB63WP zLb*^4n`tDv$|T+UR~|hgtWF_>1<+^>RdG?w3iwf4;p?SF@FPxM!o6&)Tpn6`p=z8q z%(Sulc?AXQ%7Zw<5&PpO_A^T(iX!A@(-lt=zdeXpV8ZFlyy;*&5r07@4ws?`Sh|4h zNsEYP`en(E_NHOCg`kJhrVnB2Ur$cDl2|2@d#}P#O{@}IaDcluOsOU7ss?4x;Cf6$ zU%_#g90!1wNj6Rna@UHa^2es3CEFZ~td+31R6d~N2bUqIc8jT=z;wC1l6I2#wR~u{ zN<0Q_c0|17p`nx*Sz!5KW`UatG4k)QN)_>gbLP0Vp$ElMp!_Oy@ieXN>v`b32?o2D zbKgllY)04AFNuq9{29%kmy4M8*o;$A(fizccp+(W6oMzJCW$F-c9EG<=bvK72>FqJ z79=!|zDVLXu#LPpODl_a5qN5fQ4;Me;M4%RSbL(g)@<`T)kQI5rNF#cu}1(Bd@Ne{ zic3CGG>yjg*(l$SI-$gox!_j|)a6`sFs!N<5xBXHku?1B05ctk9O zr!z#UxY`N(rd@{-3OCoPgafy?rw2DHuC9N6u&hFG+Y*D48uynzTs*PKbRCk^zx$@I z{HxD<317d_x?!RxQ%~BVmI_tu&qNR4_QpX#Kc37L=_#>ZX386W4}}zEO>+_GB;aC$ zxzZaP6n8;@-Vqifu8+p~1sqc60rd=><|22$yo)p!YrKda5jBw`?}Mm4nNN`)fkTc_Ju^|DFZ7+#nqf)V<=oX>07j! z!mv|H*p=C^mR|95PHc~QmEP~MTfbebbc@eG=3y6O&e5vLx73s2!M+UX;MD5ZoJmr- zQuNWSMl>YtqH7=!P-UqWEd5c!XE52IdPcm~eiuW{X*Q_LSoSY`xKrD^b#lKd{}0$X z*VMHw81}QN-b@U)3TqUc;F)e_*74SH0*kjPG8WiZ@F|^tHd)!<*EVe$y@L4LU6We| zal6@|7xcx)sW@eF{G;6-hQH#qsnXDgYP%>IcDLZY1r%(s05?J zirEd}5{<%w<&wAy;U?`4fO!+)9UU2Yx-5IF>$akD;nB*)8l;e>*Jp(c^aDt zWQeu59yejSv!0{y9nw459OX`if}>-zLmu;R)_|yRLKjh+>m0oiJcQpKveUWtPm6fBI#q0-*15kqvir|LHVLu0-K!vR9`; z=2i&~<@4NAS>$8Uwr_RUTwd;pZt~~tq2}7bbG!=ns~K;_RcmHaFcZ&Lg$=LTTkH^Q zrOXah!vE7+LxSzZ;M zwo4n}C%K&;A)?2rDJ~t@0U&zi82vQ$KtK-JseBs(00z{D8Ha@TQ?o;wjqRREtzMEl zCXge3o|sP3_zBhJ2ckRhs@>t3bXHG$0DHVj`TaQ(XKWWZ*Y3WOOuX^8(mW0m8jLbX ztvK|~2VYfp5Jlk~h7>e*5!J&6eAN{}Is`s`x;5V^KVL zc~te#jtla8j$FEH1S0H4U`pxw<0euY#8Ue&f+Z8w_t&1qw(BunV6C9%K^jz~@|u?} z_6jNe6%R6TyWCEzr}O*<{dE09Q&xkWW-q`Hj-2vrY?eq+e^7=tjrH0A<$p79_6I{! z`-f8ZuUWSPfJG(xGM$mjk#tzN!}&|}KQ@M(*$ZxPGY(^sNncj)98T{vbKwP?&cm@m zdRY7o+%I+1YRG)NxlAXJ+6Sm)qs!}wM&Yf%P?w?Qig$Y6BZ2BuOaDbR;RGx9d!7A^@p>gr;AZ4FQO3O8=r zBOiVRb~R2-nf>kJAj3s=6=m}5igJC=W@K~W?pWnm-#(Y4s!BgpP2U0ywlW2MVYjqB zwp_#zfL&b&Z|Nodp(H_i-pAW2IUqjHROGUJ*?Zd4#<%dmZA!V-VKHJ5I@hFcDKVH} zyOBg24=a!nd=UIMNMk_&s|S2O)>@OX-}-g6Ef=d%atDne6GlcoEN(EGV(lLQO^iv=aLx|<4lXHUer`3CHAvgC16{<1u4&2acd7* zU<1L-;VpRk%mg!tQbje!o|P}Pehv)1J;Hf*B3b+wFzswzBw}#KpnkD)HNhW{nT@w; z#1r^yPZqHrT~G=${hF~&8EE$F+n-C68FZt3jOh=e&Bfb+NpsyJ>~>|e!TrY2f2(;Mnlu|_T;t=n+DlLMxHT3?i*+ikGKf6Rpy7m| z21zCqblt=XrtHbl46}x5Irxy@!Ij`b;DzIWML!MGM%L$lvj&{4w9dI7x!T3y4V~49 zNN(Z|wQM77H!38&dtd%)q}_)9lLR9uI8U>Hl>8Y~07XPk{#g4i@u7`V|8~Y@va4pM9L*v~2Ml1p) za6v(X`HJ?5&!(j*f`Uqp$<;#$KJS_Z z-j0RWerzFax)NY+pl-H^zgVz8U$@M%c-78s5lANE)SI(dHlr}(ZHz6fBf!R_8Mku} zi4IAo=ke&IvV+VXvQ}JK?d9KA!YtFWCX~pDU-~omeTUAg!oqt178E7 z>SVfabGJ{ZPeT!mXT9pOt+lB%ztUJW4S$%*|H4vx*}+$Id2)a`7xLM(d%9~PJy8J? zr0jEQ)}LXh+U>XdL(>)x#jNL?K|967(_|6a@49A6t!Ku?n#T{g>g`Gj(4!QRh9w<) z*9cQr8)lFoC)ycHmU2mDnN9oC8sjtE}T?F3otv4cBSLuC4`1p<;R`b(BP&( zlgZ#3@jD~}rT(49WXtz6H;n1iVovY~_CfOgT)-+eh;A%Mz2e))dSwZMlTLUhrM|)R zaa}rwKJ3YY@`U#K3Fqf&R>EHcTjaeZ~l;6K$`4uJ_r_CIO# zZVj>LpvkArLQp!M2oy$LTh=K{A#GC;mNBLQIR_Oa(RkfnE!GYo3Rq+ z%I@Zj!t@-r-bTM~=-yHaSsCrodk>?~yLE7}eN)QSMBoBF(*n9SwRzMiFOgMrwKTQ< zon;89rau)!;r&dBE;9P)GFXA0y27n*usFT~N7{mcn^okju|dY=m8VCeC*YC-L-{0yc}?c1dK5SE}sIgZd7xW{Ue8h@rOPizMtE zu+5&0exy9WA?C(j}Pn#i|eju(B6`rqs=e%*~p^I>n&LKs(}L?9Ei*qaIT zP2@ylY||pek{D0IB92_zApG6>G)OY1_mm$hH}^UekAOIb-yNSqJ9(Ee@gvOyFs4_4 z$OajodA0YADqx)CGP;do`bZn(Fdz?1aqooBs4=3$JI5Zbeg;92*EEp(!7ZC) z*YL2s_`u{|o zD2AZ=JT01^O@331&4gveO<|(GX=D=m=3AP9G zj*e!~7E&;tg~^4Aikm68OqI-XbM!U@L6r}qBuu7BZ8J2gMltV>g}JfFO%l{AB2MIV%F8{Sy-My^SeYdk16F+@ z(KDQJFa+-#0>Um;dqBsLYgaoW+7-w-0C~N(8~&Icwg$S7f8(A4A)EmN8>LAs$cDic z12eT$aj{Ms8ZQC?To=rV@pC@vsjBhRarMoexI4J-X{2xux+zD()7{(T$eQwWXLef& z@bn?w50gRb71@{)x-E*|{f!)S2Pfk~9CRVN*f=r~h+pjVTDHYTm;0kYd?%7tL z^%D$7u{<^E(siZO53A&o&P9{rnMh5&$Qw*90T`Z0Xz%!Xdq1M_N%DRx@M}vZjkY7?&DubYc*ufH~vE>&hqenXBeHJV+ z-QS5KXe7Op2697l<|)o0AG$*;7x4Z=jPs-v^F9}q|4yGPnTwsWj*0*d$8O zgYl7dmXRMaZw0+=lGbZ=yhjkx6}7sdlmTajR~WrwNQr@N`$e@WOJd{=c zD)E~8EvyH$y%Djf&94Uxy%8y;s!EF=p%pU2C7nx)Ex;!oBreXiq&b0UioO!2aCcV(R z0tj~m5ha(QB0V!u!ogiMJA>iC?3TaU*lAm!nd`?i{F}ziJyRXBL)?g_r777lg2Tn- zcN_`8Ro%DHax<@CmIq`VG#GX3mv} zlcS2U?A?_@@Mfo7zbt@e%g8)?s_)!EM>g|$NIXY_{;1?O`RZ$YRPF<7wt?IKRf3d) zrYSS%7pN}pR**zcQepgymfuK$af=1bDo69175i6wS6g!!Hg%=12ll1jKfZ%fX&>SU zSqGu21CDRYae5p)ZC3r(T+tsR2aj!42U4vm>B@}=Ea|L-702k0$#e6}Q_7Z0ghM)u zl9@{WH^u00OXWTU96QT3sBFeuyh>(L2(0;l6wug}?(Za(kp1>!OZlc&J zt8mkQn2hB+9jjp&CZX0<_ zoXYD^ol8r>`sv_Ly-K|VSi*wBnnpg6z3soRG~a2n`J|_Tep@~*bTL5fsdIy$P&mud zE7tOK_V&fk)Zo3?Qt6xxBeQaZpU_I@$ClCMTgI@!(Io%jJX zMq5ohK<`LYL;R2LAl%Q^wH3#5H{zO9giC5{8-&_aTip#78Yc9o{zR7?W@l38~FFJ5acvt|v=Y-?{q^ z5w*3nb83fkO_JIM=AmhbGPX{ppZFleCLcx@cQT>)AMY3X&f8wRG6+#xTpM1VdK*on zAR|yik$p~X7`K(p-#mHZ-)yhkW`1jYGzEhO`|aF)p~$+jD3f@)vg362D?)P^aWMMV zHJ}>mH6U)z8o7;($!UAISum_KNY*on^OE-!_P5vTcc3_VGRPWva>XTbbCrH0 zI*}?QQ6F7POiYs%#wD9L(LSJ+?<4kPqSCTxhdU#~eC1f;~UBbSg8ZiO;2QKRT0@Yt)BH zOni4zv)`JHCvs%w(D@SFV?4h3Osy~*EhD|7x;I@(t6ob>X`E4~^hW z`(@P%%faXFfpNexkfwD}1KOIw-rpMWCySHQecHaWI!N4cCpBTUJ_|G(`LK5Xv}EK- zTE)7qT!%(oj$9*myA=~3z5Z>r%_a#=L6mwotgCy7s7yk2`ST)hz| z<4jChGmn%?@~3HvkXTt#`U9hOrIyqkhPKp0N}8Mq?3{fb&#aI1B~wa=5X#8?8duf~k1UV0$8`t#2Q+lIzkpgA$_W!lA)PR@&$-um)=o zrZCwwtq2P^%k-BL)Yg_oJWq(A{klU5>+CZM|mWxiN`mXFC$o_3U5uFh%vH_c|{`UA%~mFu!Ztq0q*7bqf*|&gI_ppjOI_w zmBh!*od$#d42Y$a#C}l{>b~%tHF3u!kF2*7f`wC}M)xM@aV-=$_WDdIS zz@^-Pn+M*-dnmS${4ZPJo;WYG(N&s>Ma5Ks4MX?e5_U#U4#UClXAqY0RdKWa#^(vH z+{&Y6W5MOBEro&@Y;#giU*)k3-98K0BZqXDmQ8`F6bb%IJ-cI{>6&y~Cl5|fbBH_$ zg@hJ}RfYw;W`>Uq+?~NwAL!Cky#|9d+&I2jG^xZ5iM@#v(1Fd|7Yv_A#IBFv35s$G z+$LU*g7s5f{rTMJO0e;02aB2WB5g&Oy?|Y zCQ0+F-+k(b*Qqy`R3gcbFi{@cf|>f!SYXAB*e}9(qTZ_CqBJ6vCc0I>`$yG$rl+RX zZ`dBAu1L=66ZgYL=)&-U-l7w9zP=g==fsvzFh)n8{vGC}+QA zjHN!0RoUWd1_*EaEhi}> z)LBb(1rJuR6S<>S!>TA)#M?wS)KUtCdy85oC5O%GTfy4h-VK3Ll6$AnZarfb%?V3d zHtWC3qbwY@Z0g`chgs|f(v1t-p}kid=j;CXn~_WFg`kfI0VBMW_`=sv)%{y@G(MtZf%Y9w5g^rOfX zrByC-@M_)jVS)zC4WsA0J@BR4s=m*gFvfbr3Dok$=2#V@S*$GF8DU|jO@fH(06w`6BW>~Omf zV;4!NX+S|_1ZA~2UkJ8v^;5aI{+H4!7iM)5 z7g-1IA$=b@sCw<I(si7d7{S>V4%XQFF{KO_0Ul_o8g(lt2 z467R0g~@T&6(brsuqLmbj`Sl2PP7f8GNGc}tq7%jge0 z+SAF@<;zhU(6S0+Ks@59)TSA*TH|A2)1BF!^I+do9O{7acyG0yPCozWVvc47xU8ix z-27(I3}WlNJ%zZzquX(>ChkA_CI7T5t9fLN-W5ZMoH%w7!hjVER7f>7rcdI^bwt8g zHxi;0$&K!!CkT4H;9B2&0#>tEe48$wG&y8$WO)nzkZ8D3-`(Rr7*VB|Fdj)qomw^V zju%y3HuZJQgLlR~TIF%iQ!#wn0e@~e&$xWcc78S!&tk0<3fcA;eJ8Z(@Jl`_Atp1b zINWR%u=9b8j^c!|GpX4(nyO#{$eJ7dCGpH!oOqLV|r@)7|#8w1YuFBuU^O`^L!r5=nI}Z`n`s^o5MG}d7nO*E=Ujb zuJox)$bw9h#KEyoL)d!Q!lZWWZ{~5lbfW*k28_)#6jrSUK7=+s4OGS0dB~ijxbyBM zS6{wAcGN%D_)00I849qEdW>H{Iu6W#>%+j^q#P&U$)O$#J|zcIh9~&Wp`325gn4j0 z9rKLFgFX}P1DPiAPM}lleYsajXBF&AyTpPgT-PIG5xUIy?@2vTa)?3a)S)unvrkd& zi&FG+S=SO0-hCDVy@kf$tIh?+ke6_PdpRD0!O;m&-k7A5xs%}6dPb_#ti@FEKc%2F z>+Yv$IBF3=Q)8dG+dI%l3MSXDC7JP@-xE-zamn}Ts)xx}mI57joEE(aWJA6hnYs67 ziUn;t%x3@EACvy3^Sc)OCHeE7W0w2GjRwUAk6lS;`8+Y`;SUN=JEf^a`%C9Mq)#35 zPfO{2cV>v9hMaz!=BJi8LK~N>FB^$e_ajPsG>o!JV%q$J&6U$pwbkSl)vnk{~yKn{|K@FtJ!8@ z<>2_gnr#LK4wnB%wEcbZKLT%gI$<+QMsP_x<;^%jSh>Kn$QJOK(u~*Q1<)C-9XszlQT^h zMlV1Z_@3xzh>|D3K?c};ye(hkX|uhne15!s)^&bfjBj`U3hqkw>FVnKY}V2KJo~a2 z>wFzAidwGj_VgH?E>Wouicmgbv3}Ht`?&wSeWUxjum2y}c1ZSvb1lEm%kb;)pO5!$ zpO?Foug~#u9ogdD2b-@OGVP|x)#umg`_HeNy$n{2Bb@;G6TrloM~JE5SK9IwozF|2 z{tQO3cEHo_9*G`{DAb95U+Chid90Am7K9VDn64Ya=3pVR#r$P_#(;eAkS>neNGI7!3y~Wz6$wmqxnA;KsU0mHnWo zEl_C+G4gGY7~IPZ+JH2*ltBGOiuGeEV00JHYAuXmPnk^9EL$k9msj1l69XK3iw)mZS!RYCMe>$_T00ml*or2x$MtflmK9Q~ zzN5)|TDGtrY_|FK4bmu%iS!dKYk(h%HTmo^J<7f@zzdpsU!enB%pIQCIInk&jWzUn z2?LP;?G64+A7@SR8!X3+0)pTLaaWcS@F8cI%$t-K#`OK}GfTH(h)@e3=s^9ZWRgA>7$J;dl9oZ_!NeI}Glsbuc6Q zQ_=;LZzFl~ZwdsbuJ{(W{viIuw<&-;IlJSvg ze_ryRd(Id8zJ$h4i&v9Y%f)Gv=o`EAs*@D8nIoR?DaclHZ1=zNbgGPU%u74qNmxl@P+xAMY=HC){LKw z<)6=;&x0N$3LRNGhdXU@b7phk-uP_6N1vOep?_<6ZI>pZ`!NOgFULKfXJD1Tv+Jqe zFe^59H-YO!&a6$^57tnJ43ujfdcnbmHFCpkJw}}~Jg=+EBINn)Lwl!wZ3LyiEx5HK z0$b*Ek>?0&$%awVgXQ>3WqfmEUBm5Ne_kcsJdn*SKYZ`#Aw#dLyBa*46bKt5_UCrwz|` zJm`#%WVd9LmcIIe(}q%`6Sbhy3pX!bH+64nHm`-)sN{+`;n!hZtC<1M{$yz~3tY*j z)@gf7z7&?)A9kp#x<+VFBiOi^ZG8B4%bvfh_pa)uo$j)7vv_lLvr2S}ArgDg#c}7s zv8?h?g6xcTR^oJ2EKBFt!xsEkhHzmX)H&3WcH=C~JqoDnr7kh?=IgPZMk=?TbqQ@! zc^&CU@B7~5{*LQ(yojujnrY|(i%(}Kzg%lRp*-)L*0WR?*ta|3p`rh^3w^O{;=|ra z^pEvBG9w&1d`}5%N?hzNqgrjWiHV?=Ibhb{9ou_K?cN6!OU+-Y^savH130Jj6_4iE zYa%rD4PEEQpxsrX+ zQ+8P9>Z|AMYkTa?Zk#l_?$}V}5?JN?h3<5-|3wV{Ip*Otx#2EBX2xOBx+5oC7L#4f zxwyOHueTQPJ;a*SC`6fiT%WGH9GP-PS0uO2|DE4a`x*XwKYwXThcT!s)ntkG?eiiT=TBKX~7*t=dYo-PV#j z#IjdJDZ06j{ITPWBHz*!eW;QWk3D~&k$iE4NzL`8ZJ7vdjnTLO^Ad9dp>WRU(L;x> zL^?kK!d~sBGzs~S6;0`1XyzxRZV8oio)_cP8nAg)$t6pZbUOoIx9(L(FDy&|l{bC%LYjb#FJn_9ScgSO(e#d@2^G{QPWhOh-(u z_Fr?&Op)vDd@J~UIF$O`k_HQ1kBGwBH+;KJ9wcP^q}~v{5h!MquABQ=Ds>&7H2L-EsDxcLMi1>3DpAf2Zq@y1*_Sn(6a7)^?Ls{>2l>1rXF~PgU zFfnB2uqW=qu?v@jx>6PIDM=O|iYDPbs%?y-O|#YzFp&Lc)sR(>PU~-^W?|Bcx{@7Ss%Z;>Adge#RNR@Q+E$7O+D9# zJ)!Jwyr@SCU%%Ofzt`Bp?5V$X>_ULQOGZ*BD%r#0dCa@Y7$1#@U=g02cw3=A2fav) z@~_y~_?kZ`kC73W8F$@o{~;~FBlFAe5K%*k5|9W3g^7kM8+UM`tNwNoD+>z2DfKT$J zcggy~=A%wv32{xOp%JlL7~|h%wV53h#NO>BC(NA_uXwrC<)*Bvb4KRCKun{gg|B2F z`4`&Ud^%=JzrT?sr7?e>D$hv%@f{^7U zFn%e?F_C57CSY>m-G86CeNT|Nrt4wex3eQtX74705}pRW45-xpZW?;wyhv5&zRx>O z$n;BkRfyftK;Z+UY{Jg-F0t-Ss+@gV*5cPs+GG??eKVxYximN`V(mOGrz%SS{?d)m z*Gdj8Nxz2aZb-{89s6=QC@A1*Tw(WnYvCR8w83OB{{zOG+2y96%eJxI{JNC}Rey7$t zmD!Q=>*x1o?+NZpuec%O?^ zo%B%4^`Y*rMd=?c^lR=OxlF-q6rS{=lY5u7tY2!r8=;H8V{9mE@=Ihc8!6(tfmN#+mhG+#H<;<_$vhQjUn+L9k|q8Z-LdOLst@b*ii9qz6Ra~61@mfY zVfN_{Hh0`DV^#F&%@ha`^q*7c|Nf=5F7TceFZSILt~_-)R#tx0(7gmBULMVt=60%b zV)V%&kz({rImg)*&t-Lf$Q(1ZpH7Uj6LV5wG;Hx@^5=~6H`Gr)P*9gnxK{W1cww#w z@qzs9ki~}T)N&7P^=_@4PdwT3BOPJO4^#@4m1sHBt_X#(CX~LzT^;Y)Vw(!to9kC9 zlO$t4sY&}>o}j2<-s605AmZmRDv^qC&J(@G{mPQ}{IL)NdKIb|!I!IwE^?15wy0tr zvXVbsLtf>~`fxy7@z-d(g}@N6wh^(9XfXq3CcVRE5@D%lAADS9$(Oonq^oLh_-g(5 zeG#E>N2@%IM0!6yr`*x-z{T>aJSWGNN)r!z)A;GW6}P)r=rq4+^)ohcmYw)vE#^;N zI~i)XejZj|EsmvLXbfikWpJ_eQEvV~V_c z-Fxs|U?<9FLh<`>pk1fy3*JEM{Tlq(yJjjpHgm$9PwpK3cqm{#xZu8t&V1vQx5>kc zuWu-3M3=noEJvIAw!9jue7fW0kNtP`Vj5V*H3nWpUDzmU8dv(dZ{E6Cp?r~FyR(D- zXZS5{xhVSam)8pqXPVU9RlfEVpK%~eaIW#*=AimLR(%z;T!QyC++YI7*}) z*!gY4sO^P=Mk{BmvGS^kq0lIen$`#^GQQ%VzU9fPG{@GROT6oX#5AX1U*;`x4Cgf|ef|laiHh8F zrP=&{{LK_bF6ZiYFV@*;3Y6AVeU!U2((4&P82Po}D5Uvj>fRO8s~oo{>G9ReiaQ@u z6?*vozL*j9=bp*TBSXHk)x)#XPm)shY6PwMh%RlEKj|?oU_I157#-_ zErT7Xc^OyyFAE6uep?btUHxwOWsp_PEgvn$uOi7&zUQFIt}pL;-9P`n^LWguC2`l+ z!m&n-3QIi$a_T(8rVpACWb-PpMP`043m>zmNxi$KXK3*Cswy|$ zOsOV7@6Eocl@x~6V?9C9zJF4Th3(`7zi#nj*)I)+8h(iqyPLZPLlueXAAGc`*uK@1KRQ}mLekE)H2~g;@j1GT|+_v)8`c>9j@JMdzu>JYwRO=pl(HAoK}R+@em(h_U;B+ z&8Hq2*_bm;T9swbyLIFhAG{YxE}00fFkgC5xhB`p;1k*Po~hzsB&$%6Nx%uGt3giL zc?aBXS4V8hl_sy2s5LopM2|((Te9-pTwl??ZFZT@jq2WVk7MX2o&2{NTb89GUTuQR z!lMTRDP(I++9!E8s_?_F$-h8_h0K(@OoJ&@)-E2)velZG`=?F zu<-H6Z=Oz4&+WC8dLAn4Cw7Yq6%qBfr6^GppR{WAec*4zv7>8Z%`eqN0w0VFTqk^1 z=WmTUxsPq4j-_`Y?ltXg@iSG57O|eLvey{fVuxIb0z$K92P9&IemhLtA#n`hiur1D;>$#r^vivJ zZ^wRbUA(f3>h1fZ=4$2@j8!A|>9a<{C2C%+zRNfn85$+(H+ay!#&w(HClf~!i+L^8`u`Z_8m}sJFP|Kf&pox$Mcv(`a5qje;>-J2 z2gcO23fm%c228sat4;J}_wcbyKRmCc`=Z_}wrpP#Z|#L$&yC-{)oYH**|6Mr;1t5?C91A`pAzwy9k%Nu_EFx zN>g<_d^MJ7NjGxIZK}l!Tyy&beMOX=a+E~R&HTPA%c;TNJLHm+vT9$28+E;G^Q~_A z>#)1iuj`dD@5~pBwMy&+U8)zH=pV%t*3*}~>%ZB2R_ZU`&LAQemne2p}Vg)MXSd8 z@p0mj?t#LdwYJiTw`1u+0+pkr!ymc39IK)mm16MMV#H-PYch|@CFYbp`+A48)__Sv{E@Z!Rwbxpz67~WF^R6f_Sn0;}3dETwml`iW) z2g_7dhA{l!*|kK#g%rnV~LJS&zw-}K3dtFJ3Kd}&ra!A#zPiMj(rRGBeSj$2B9kb8LG z;M{t9;fThy!-sz{sM^*T@9(}IfYbPKZ=uG3-a46J_Jn+^`G%nYwb7OCiohwR$%(;? z@c-^lGMdc1O~yAU&u=gW?Ji=BH&IUv(=s-(DG&But5>=IM#fOUpo2*y?nsVs`?zq! z`?TVIm(=Gc0v|LM*eT94et#i=#T*^7D-3B8+sJxM$2CSQ8LBnE)jv>Yzv3-L{_J(N z0GrTALjURYhT*E|S>yaACnx2f=VPo(SW+Fw%3Xi)6*^3LnA9e)xSwWwv2;?oN==i# zQew9tq4mz+=k5=WX)=|XOg7N+*p}1s%-ql!I{dgOL(w^)RH$6dNrS07eqQlsYx#p) zN$heti$CaC<<7ar-!v3tE0iDd3k;3qv%JS)vQOyge4<;6@tY@83yFM%iXuj7H}Dor zLO))t53Q_T*z(c2_gnh7LuL6E15eI#Pieu#ZqYhZlS4bx0%vo(Cq;7;*)?y;?R=9( z{X?#jBbC#DHzsS2>XD4B-Jrp^Crg8~dV1bY4nL+7Y93n?>Ku3Ng-=(tA3Ek;kTS+l zAd&NclV3r_S$to%Ur1WJnA`&iS)L+Q8R?&_8}8hv7ET;+!>}Jn4o_9Qu3=;)so%`3 z!Fa$cyw&gn?-f5$k!q_dHY-W5`G$E7b;5W3Cz9UtZv{CUBYU*%nDXyF7wI?u@=AJ7 z!=ObIXYHXM)_$~>MTdTL=bNWQs!RpmC{XpjLgQ_qA+1s7#eE@orYMQ!H9C{JnkIRa zxOTHyKeCr_`ut%L4Phs3Yf-WN!cXzk-=?nZvl<(juIdig7PW6|HRX_b!ZM|MqHl1( zz*_9t@|8>2NTR&`sUw4l#K?bt$oClMmTRu-i!yW>yiv@%VG_kdzW*t3!{Rhg?IC9y zKQ*_-ti0&aedSNH^4f_>&t?yWz5U30Q0;`EwzOEC4KA|zZVZnX)$XF7J2@r-UkJ7M z#v4khuRZKjjl-XRxNoO;iu6T>ocdQ?1-y4$C3DS>MW%lcUc%}41cx!DpNj}msOu1L z)5=GAg-jnT96RH{Si_OR?5r(-RT)31dD-H5G;_*;Zw-}q7CWuSVb;#md%UJsEZb~L zFMcc$9?j6^YIzuJ{+0$!Q(zi#pouBDeXVYyY-Hm5q4oUrAar`cr8FVFnCB?{Z(s18 zA9ajX%I_NO8Y-;2%cmB*{@~6JIS?jEH4_K-C zt9#ZyaI>0CP&x7II{R4c;q>@Yl&7ra^f8mWej7yovSs}fuIiO>Y>BnYyFG0?Y%Cr; zF~9!fXzg&mhE{jryK^kQ-bYsqBaR*q$O&>1n(QDA@U*TwB^MmA%}yFBb>R76;+7m; z$0c}};Yzi2$Fr@P=PU+ROsjFnP_6CEz2#5F+>*n`p6W5B*|mJxl6YF_auvt+0Bf=F z*rj-_CYzpUAxm7!=y}=Tc)FM&=lAP84IfD^u1>k-CkoxA;tUa=Hs2gz(6CTb)g$xX?x0Zqq5=~R(OVrQNYcem!0Xu-VVP))b5(xJI>u~D-oU-gn^U~>2ygYp;=RX4a~G<9v_Eht zKlRa5*YYB&h_CK!fTrfTBTZkjTx@>qCK>T2j3t~OvahT8UMd^;ZtG%X`Psh**n`St zjtJww_(XornitJp=-HZ2wU1`vt<7d6e=_CCOTN?zEOYx`Jm@MGd&iu=JA!M@U1vA* z-ROp)_kBh^=M@ckn=Td~ojElVuhlDXSh}=Axc!@$!3m9DR?alN2lKDn*ysFQYo&=f zu97UA(;HXA7#dbUu)xfGJD=aCQ5n&3?&9|}3F-XkS5{kL<_ALaMN&!p3x+wnjz~X@ zT{|EDN!2`a`AhF0=lzhx(4=3_HbVt}8Xs0HS8?9ytnNQ5N?+OWg3eC=hUBdsrj9~t zNlc@xr&j9QABGvK|J_1kpFgK}-D^qeGIP3>(l=4TzwxKqQ<)u4y%07|+nlR^QCx6~ z;S;Nf-$B9f$6OBsU-WDZ?>iltEJaoJ>Q->8Dq9!9aj-ZvHd~DgEp>NYQGaR2-SYqL zwkRZsejBrKi(QeN*?H`hMnkz52U|hx`%fn|QuO>6+kds5R4N@hr%PjV`KhU8xzssa z$BXB`N32dMUgnml=dCcucPajUiIdnlvezY17CSm06T&1+L(4NPJalC=VEX&74pZ4l zOq6ZMrJ=HZA0BmO1wqF$;c2=YzD|Si@}^0fq|a@huSNdQGuZ5WQ(kepOigaHnmz1T z}E80uHqy!(nSWv&%e+Ix3f z?j?z+)1P|1N?*YrdH=h~NRQmY$6s9PtI=cJ?A;HZqM!7hP%_<{&c3)q_wngFEHge^!Aa7M_g9mz1QD9Hf&WzJzEU>A}yeva^%#E=9I>)f$ufX zkU=MN{uLL?3UTk?hw~k_Jr!RSS{}VQD8&*nw`X)D($L`Bj^4LiREHAJWO|amx-C4d zh#>TbC>;0asMS{xRE!gGx;aH0qosK$c0N)m@&rBCb&`98r)Ioq-e;0RQ_>DY^CE#$ zI}SJJXAcZ{vT&5TYiLZfaX&mi-LtjzedkAdF4K>0ey88GjR_vJ*A?E%Toj>m!OAu6 zrWZ1NS4F-JTXH`*>+u^pgJ@#0-*mT17JulAqj_6VlSWDv`Ir)(WPZinF{~kMyi2K# zT;^se4@nKrjHt;sK$Wg@IIQwL*}9THDQ?Gti}`|G8ssmpbTSMKpqe^BbwE8}=a7PG zL^Y}5X-7*ee~bBKQ~aUadg49VoJ`##j<3?2FQ;XU%Zc=cE^G2FMRFZ(tY>ro-74q! zoPK9{Lg$R*rmWdW*%zZqxcB&*%Z1qbm~z8*m3+hYe$3f7Cl7F{mAhO&O96E%>4dt@&JR2BDKcL7tj2&P)(zLYuT^v=Uq-a`;jikf^T1y z>dT(e>Mb+wL8D&_R^wk|Y)^Ex@nlVG@O1|+jZh16&N%+=`~KyHzRYw)?Br?T8`tHh zmkj;7gU$&?pO3k7*Y%6EpxTx9Z!GUvWLqZ%9Z`)~e!5oI;JY4tTgHqdb6obtQrT@O zwY(tZPiLftv1`)h;*MTo^m_s;9XvHTEIxhu(V;AS&st=Bi^%KnEosU#+(oebm|1OI zxxC=((*oAKrvm5)>pO>$J9)0^j^~sOBRS)Qnt5CIctQY z#3lztlsL{NIkM1W@%4O6oSOx@=MMm+KZD*;gR(R=$?{aX8 z^^juN)O_vjH@BA~`aIL#Etk{>-*;UaXq3`!FOW6IbiY8+GbcWfoixrEnzk8NIH0C0 zku$+x;K)G|ofp1xt(F@n>P1tqAtW)>GPurLCD`df1ck!bl{4v-ifxbPEy4EG@psAdPURTi-qQ%d*pU|YHIsWhMXDH zJW+EzbFWej{j0snsF-XeG%^^PUdV} z(F7N-Ml`O6u_VrW@$2t*7Liq*6S|2EmGI+H8fytHoM_Uf8D1IJq|+;`6(gZ|Za%&SiP?VRCg@*YNqN9mGvGe$vBR>z6Bg zzbc1NT{SiBdhkA?-tD%M*wrAB;pw82=>vfm(i9%F9PyIN2|DS2BFDqa48Lex)j6Ab z<}>k99iQ;%y-qfFepec`kDoGgt9pZvgenI!*AGv4>qTh9iVQ{FRmhPMo&R`k&+Pe9 z9mj>C@TE3tNps^-Ddl^H(#s1DeWi|Or`)Ga+{D)!oh= zFVEeh>95-|Y*@^C9ElgZ<@-3>FW;)-rM_R51INc1=TX0XnN>kH&zO#JU<_lEl*X8H z42p5@?Q`@qDuqU`QXTPqlWyBj80-~z)kt_=(tfXF=>6X)`}NSiHy_U8(7Dh4Yz6Jw zlonupHED)JM_hB@G<*1Dc)9P*k(_?+LWOnTD<>YSf5MLLdT_N^VK%y0aEb5XXkk1q z3g7zS>uEt=DBXax5- zbvjBXjsBEenk!B+J>FuXS92R5I%R@8IHc17l~MVmu_=JC9#t9A{}s)vLd`bSb@~`%^2;;>{fu4p#KN^%i@olXm&rRqmX4 z;r?xRr_dgRQiGJAG*g$JyiRZ1LvHIR&#I_eqwEcGA9nKH8qUROtF$L_Dp$?P zmgvWI^6xXh#Ue+|6GXVih^+lXq+U(0>&ZP%c!>io=*7Kd~5&=1}Gpi8+%+Alvc4fDk zU(T`5IWNsRz@_diS}S_0{iwdypA7ds@%JbH=y-kik}J09q3^l!-MDCaqxY~8tKnYi z8+X5bzxn~S+a+Do?Ic&uJnoR$j*XhSQE6gX%}T+kvir$5UOZWUmFgGUt>YfsJ1p3L z;G=D+cCWa3#6rl5=9S=eRDt4ee)ba<>w?rzh8lt%+FO!;NAy!wuRpkeoY4V#!mz1U zq0zP6CCkFl#dv4hALK?(og#bo;+4uqF}m6t)=b*=Yk@1BzOT+*a40=K>b<9^$F}dL z;hwq}cX_?wjZN$XTmAdnifrnC!hJTdB6sQT9APo%v>-e_Yhc34U2nSoX;X`H;G1Jh zXZGj)a@2RRe~8K1b&HX%`Fge0`ejy}mZirKeFaa^MqK*dXI85w!E0?%siG@c2I72| z6pL0MzxZyV(mZ?_Ti4& z%pE0X@8}t{S`=Qv&cvJNelR25F8exm?$lBLSD7h^9PKF^>TXdvr{b2A<8T%_Y~C>| zS>nu*PMP}t9qP6>Yma3!?2>*k!f97i^`*4osr6KQ>PG|R4rS5b+4GwGX*Mq+ZKuy# z#w|bgG_|j)eL6Nb;akk@UP7?n8+#|PF|bP3cz4QOdk+m~c_9VieAN8QM-$VFyHDrW zozfV(tae?bp>gwk$?@w4w8e`PZS21Y9j z0uSD5J&92ftj`~*SM(bwRXO?4MyXbUJE=Y{IF+MXV`?;Pc;kj?U<5*%NL1Rg@>bVke>tOWbz*ZA0lEnu)xdo=3k7^a>Cf)Ys&D>DwA!^D6 zEKTindJweO$H^qU#2dR%{lkE|k^0Qcr1tRp*I|2|PaL5Nwxw=0p*3f@A$eBDlByJY zCSN!?a;(BMB0})tN|b6~NV0_xxj|@<=`vI3jd>7Q%CqHk=ppI;bW2&$k3_*ujO}r@ zd_`IP-^0VTKmO>P_#wt@a#4)u{GH`G8aFW>#Wq`uoxuiFx8`E>Z2UJb?>;4U<%j$Y z15QN&rgtJ@=8S=+VyGDg*}2DsaeWKJt~ZmMpOGHV)|wZD_Z_OSD&ORNvPYAl2>swC z`8Rd2yyUhIy3dR{5?m%}{m^B1m8rzZ4K`1{TvZ$2bfc3cAKQ}p*BiR;jv1Qv+&byv zZ|tOVrP;u>RNKXJXb-D|nS-H_U8Evf@YXxNeC7Qb(Zk&5pQgylq!KfE6IHp1V~Xmj zX>A6$_j+nvn$CkG(J9)sL4zYZod%a)ekOzzvuHkHGIDylL!>DyuJ&01HAm!!1lr#G znw|R&SMBKA;r$o`#osOrijpUS%lh(`TqMKAGS+r{i#Lk=b?|zb zX%o|b{mXXTMsL=q%;CNdXKvjM@Hf7oOa7ytG25`}6U&hB>hX_qMPi3pS^a5W+#7o$ z?;w_J!u29e*txmpW&@)}BcsK|oMA&1HU%rL^aKSZtKC8=7EQu;8q9q9o~T;Bm-2X- z$HM0RS_ZqvNlBEgF6`U2Y`wl%nwK#-RoZv?KRcI56;urd%O5*pYhuK)5c#iBTPyp} z`E;&9`^A%e4X5(C7j74r=KAPz*Yy1^x>ce!+F6syS6KAUa2cu)#ww$2fSI~B&oc<;n>q12*Y=_Xsbz)?Zwl!cs(hn_l0bzgR{rVA?A zwil0wb665Tes#P0dvB`A$J#l|nPwYQ{OPi_DE^Iw^XGB_&G`o2oh^OV zdLndm_lla0&P)hgjMpQc6_q_s!*If#(a>-;AU*lGih|LVUCi7QnL(v%@(oY%-9L+x zWJLL&&H246SMcgqQS(KA!{Y8Tygz6vohGX1Hh*(y-gf@6lk(}j{p+olCBrB4jkOsa z3{%~QYmFHmr8}ydxdw-LoQUcPOvl||r5zN}p4 zEb-WoB4%8j9CIgYf8cU88|UbvpVTG);9kZ{dC_0!EANjsRx|u8nDKwEy3aJ&V4rKi z&>bn&gKY=L&z*{4eU0jrQ}>B6PEId&P*Rq@UlbM-+(RX-mUK`5^to3`VhY3QJcUk! z88a4&w>vpqnV96*7$)#8#n;{!3!9q`&pKQz@4OnRcP{@!AIfu2PaMmbeOwHqS4Vwx zVeGtr=3^O5SWkSC!};$6kN-VOHhuOxDCTKfepk)W+pAIriWR(Vw%Q#@x^a=F!E9MJ zM)tqFIEs!9ro=s;kh;DooX$jZPL#I~z$d`*>i*bGvpAWp#W?7;UM70P=&+iOaYveDPS`-^ot{#8R z;iB^^R{hm&>sb@Uf^TDwWMWoTPEZ9oTowAvx~TA}BG4-J3%`80$7Px$rZKoVVLgr8 z5zg3$&&NJ-_U{^|KXO0zTIT&{tA;*rbT(yCyNhs|FdCma?Y@@&rK_8D zPk@rkXWrJRKi}*eL*DaL)QC7Pn0Zu>ju|}T_!~)BIaxNdaP`GQzJrJMS64sk*`Uh_ zI*lW??$R7RT+rr3O`cVVSFL->`Fu8C<)rS(pSNdPhtEVrq7=wI zEh&yXhFU)T>!V=?)RKb+R+Y+h)tgQh?TaD;w^Aa)Nl$XyerkP~HOeLKlk?NwOD!-Q z!!XhN-wh=ew!sk$^B-UG68MlgzEvJLP5$9j;uGk3I+B|;*aE1-@d;xcE5*9&@dg_F znjs~jc*BKfWuGhm{TtAnA&p)1&Y0xUt})u?Jl9ia@`Qq;Z6qx$c3qpYCE2wo6c$<} zvD0jcIDInI`=>tj4i@ z^Y=5myXw_N*}jwoM;5(5Q+c>NUHG}p8xO0{!MG!j!(SLq9sd2da`UQ(&yemL<*)sv zGyQ`Sx7V&|6%(<~H!dmZKN=Bi%%FoND`o9ZZI7UID@q~u?JB$Uv; zIkx{v%jW&VR5O>Xnr~yt760*^k6)6jiWA=|>6OHOY`p7zLb`R7rbEk2?h?lHN?C6B zO!h?PI!oUYo5OUu8tZ`{S4G%Q_O1%WPhVS)suW|G`B?TUR+ijilb*A zv-Z4}9ZgW*Sz(f_&=El$HJizHpIOjKT>ZBqciY?gj|DTb57VP$702ENy=D1(aLUrL zZqzYLyOGK7v+a=^{8RGDDke?#H@HRK)MfQ$29L7DRJE$mJF_urceYKqk0(gv+2@@YepbDcsU^=5T4jEjQ{+6XURRiV)UdURel}7JAlx5%aeYooTti5QTvf;gw#n%rLQ!?#w zUdHM*#-3--p&~b*%&c^{lxh@~%SFCY*jx@hFt^md%S*Wcb&QSkN~+qy4&wJ44QWX| zZ)#UFoLYRXWk$>JHtQLL;#aB`^{SO=`=xHEnU;$=Xp*cm{$9SiCTp^s@!?xo=UMSL zO>rg#O*is$M|<&lJ2!Z`J59EVoT&MPM(;^S+nR9h;v4enIQViiF~$GU;g>~&dQGaULF1Pp_Sf3zMU7vth%JXUK34}n5NO@;+nI2m>O$OE zi6gDo4ygSUpFKQZquG#ti?uiJI$_d}lSkiyy-Yqv_g}-O^GxHe+F-JksYJLONrO^8|R(bO)eJy&ZX56(r(E5 zF#JH;O+0Av#f&ejA>)OJ~P&2yJ{v!lre< zL((j7xlQ*6qoZ!Y>q>SG7Q49mO_V)J?|;fyeu;DVCKBc1Uwy(;FMetOckBD`rRo&5 z{=-(iug;x|u(OLF=Q&mIC%m@oZ4mpF-_pYcV=cTKzC(-Z!b1l{OO9nUq{Y4|-gr^? zgHz`3&WZX^rT^i^O^?|BdB>x{WluX9Ju3%0867)YCo5%-O9E#9 zePS(+gp)=S1&CObG?8Snhx{epcJ4j`81f=s7d$R{+t^)@mzUA=_OLl)=VKZU>V_hD3JDSuG@8WiO_QIu~%QN9pG`AYP^kJa6SM*aH+H0Arylo|1y6 zq~IwjcuESMl7gqC;3+A1N(!EmLZGA&C@BO=3W1VBprjBeDFjLifs#U?q!1`6L`n*g zl0u}U5Gg4{N(zyZ0&4^o2a%HU@6(j^_fS4Sc@K$_LZYOQC@CaL%D=bplE0GjSV)w| zLZYOQD31kol=5IuM=3d|qm&@jQA!f(C?yJYl=6sBM=4>bqm(q%QA!-@DCD6a4+VM1 z(nUcY3i42phb(4fH6zOz)-wtgGzwNU3YIhq)-(zhH40WW3YIkr)-?(iHVO@o50*9x z);0P#^&X6i{FR1sG7E0RCxt_!#&m@qi63BB2 zEcn2J4=nh=f)6bCz=97f_`re>Ecn2J4=nh=f)6bCz=97f_`re> zEcn2J4=nh=f)6bCz=97f_`re>Ecn2J4=nh=f)DbuT*}V{d|<%`7JOjA2Nrx_!3P$6 zV8I6#d|<%`7JOjA2Nrx_!3P$6V8I6#d|<%`4t(Ii2M&DTzy}U|;J^nCeBi(b4t(Ii z2M&DTzy}U|;J^nCeBi(b4t(Ii2M&DTzy}U|;J^nCeBi(b4t(Ii2M&DTzy}U|;J^nC zeBi(b4t(Ii2M&DTzy}U|;J^nCeBi(b4t(Ii2M&DTzy}WY4;=Wwfe#$`z=01O_`rb= z9QeS24;=Wwfe#$`z=01O_`rb=9QeS24;=Wwfe#$`z=01O_`rb=9QeS25AyG(`nP^@ z-~$IfaNq+6K5*az2R?A%0|!2E-~$IfaNq+6K5*az2R?A%14r>;A)`XRT|>U(b3uUe z{FQvehJ1VJzdK2|e^UPYFY?Ww|L3=l$hWX47y6X@N96ydTz~wp8%Q`9!U0M0tt-kD z0!bW@!~sbhki-K?Jdnf#Nj#9m14%rP!~;n@ki-K?Jdnf#Nj#9m14%rP!~;n@ki-K? zJdnf#Nj#9m14%rP!~;n@ki-K?Jdnf#Nj#9m14%rP!~;n@ki-K?Jdnf#Nj#9m14%rP z!~;n@ki-K?Jdnf#Nj#9m14%rP!~;n@ki-K?Jdnf#Nj#9m14%rP!~;n@ki-K?Jdnf# zNj#9m14%rP!~;n@ki-K?Jdnf#Nj#9m14%rP!~;n@ki-K?Jdnf#Nj#9m14%rP!~;n@ zki-K?Jdnf#Nj#9m14%q=S$Np8@UUg!Vavk9mW78c3lCcs9^~M`2OfOj!3Q3E;K2tT ze2{-T-akJC@Ie3{1n@xs9|Z7003QVKK>!~F@Ie3{1n@xs9|Z7003QVKK>!~F@Ie3{ z1n@xs9|Z7003QVKK>!~F@Ie3{1n@xs9|Z7003QVKK>!~F@Ie3{1n@xs9|Z7003QVK zK>!~F@Ie3{1n@xs9|Z7003QVKK>!~F@Ie3{1n@xs9|Z7003QVKK>!~F@Ie3{1n@xs z9|Z7003QVKK>!~F@Ie3{1n@xs9|Z7003QVKK>!~F@Ie3{1n@xs9|Z7003QVKK>!~F z@Ie3{1n@xs9|Z7003QVKK>!~F@Ie3{1n@xs9|Z7003QVKK>!~F@Ie3{1n@xsA4Kp$ z1Rq53K?EN}@IeG0MDRfbA4Kp$1Rq53K?EN}@IeG0MDRfbA4Kp$1Rq53K?EN}@IeG0 zMDRfbA4Kp$1Rq53K?EN}@IeG0MDRfbA4Kp$1Rq53K?EN}@IeG0MDRfbA4Kp$evRqh z`GyESh~R?=K8WCh2tJ75g9tu|;DZQ0h~R?=K8WCh2tJ75g9tu|;DZQ0h~R?=K8WCh z2tJ75g9tu|;DZQ0h~R?=K8WCh2tJ75g9tu|;DZQ0h~R?=K8WCh2tJ75g9tu|;DZQ0 zh~R?=K8WCh2tJ75g9tu|;DZQ0h~R?=K8WCh2tJ75g9tu|;DZQ0h~R?+K1kq$1U^XM zg9JWE;DZD{NZ^A6K1kq$1U^XMg9JWE;DZD{NZ^A6K1kq$1U^XMg9JWE;DZD{NZ^A6 zK1kq$1U^XMg9JWE;DZD{NZ^A6K1kq$1U^XMg9JWE;DZD{NZ^A6K1kq$1U^XMg9JWE z;DZD{NZ^A6K1kq$1U^XMg9JWE;DZD{NZ^A6K1kq$1U^XMg9JWE;DZD{NZ^A6K1kq$ z1U^XMg9JWE;DZD{NZ^A6K1kq$1U^XMg9JWE;DZD{NZ^A6K1kq$1U^XMg9JWE;DZD{ zNZ^A6K1kq$1U^XMg9JWE;DZD{NZ^A6K1kq$1U^XMgZz>t@|q+FA&(%hN`evc2=cll zC?Ss^uS|jy@(A+UBuF8@$cZF_74is@3|hz|NHTaKk08k)hCG5KgBkM6rbsfVA&(%* z;D$VcB!e9C2$BqT$RkKH=pnxlizI^|@(7X)g2*FCG8iI{AjzPJJc1;HBl1hTNHRzw zk08lli9CWNgC_C_k_?{6BSBaa}-pp86&B!f5d zOXNs0h$D|6$zYB=f+T}F@(7X)?#LrZGRPyp=#C_VJ@N>W4Eo3;NHX{%k08k)kUWAU zBL>NM{#|^a$ZH+>4@f4jBxD4V$v-D#1d_?KfQ&#g`R{-c#2^YWh(Zja5Q8YhAPO;v zLJXo1gDAux`Q8U4BL=t20^4nY?Yh8rUtqg1u-zEgt_*B<2DVEBD8%4)ZD6}Muw5M3 zZVqf$2e!Kd+vS1n_P}<1V7ouCT_D(Q5NuZnwmSsdC4%i1!FG*cyGO8HB-m~eY*z`k zy9C>1g6%fJcAa3mPq1Am*lrYTR|>W}1>2>9?N-5dtzf%Xuw5+JZWe4;3%0uj+vS4o zcENVNV7p(iT`<^g7;IMzwmSyfC4=pj!FJ7HyJxUnG}vw$Y*!7oy9V23gYCA#cHLmR zZ?IiB*lrv^<=}tcA_S-ZbCZy~R{t~e|Lraza*qJ+5+b(>{?}bX@*_g1A}0Z)`#|pA zz)1jUKafY@B!KiE$RltPKpGI_5jY7T9SHIWoCJ^-1Q{rjjGP3JA_VymoL-PB1bGBb zFGv}JJOYmysY8%Q;3R-XP6B9TBSs?|G17@3pB0eDjBLbcWFtl+8!;N$h|$PKj8r4Y z=Mp$2BIOA32=bVbjTq@ikPjiVfo#M`MS^??dCbU0jI<=kXDMW!k&PHBN{|mBvw>{H zNLPY<2$^SOBSz{H}n30VbX-tq0A+v#O#7Jp^d{HNS}gy2$>CJBStC}DU zAX3L5A429CF^DuW$d?1iY#;`aQU>`D@)JZ1BE1aqA!MErgGe=ldCBHa!0MHVs}h(V;jK|X}c24WCt zaQq+Y-lkWxBfHX@^H4)W|K6Ff>Hn8&x#W} zlB({r;!X@i08CLgFO|x7-`L-4uf?~*8sUQh;-FY7)(98}zf=Cs0p#F!%AXui4t}Rt zBfuQ|PWd|roP+8w{^an%Ky>h}V&}kg@H@pCf$HFQ%HKI~9aNFU&VlUUcZxLv+rjU| zpBz3I@D9Eef9LSQKzLA=#-AKM7$6V671oG67&s5U6@TaO!GL=3t*}Pq!8Lqv4If-1 z53b>Zf%u?0jz2kk5KRBw5v-911NK1$9d?d97|0L471oG67~l`S71oG682Aq=@vuhZ z!GM79t*}Pq!9aoVt@t}f9tLr^6*~uNgx@LF2;2z2 zQ~u6@9N~A0odY{Uzg4Ue=n;M={^ZDm0U+U9@pq0q7#I@16@PN%!GMv_$%Qo{4+fHi zZ^hp^@?d~T_*PgW@?hXe=m_KQ96lJ3622974j&9u3Ev89gbxO=gl~nNBM%0)gr+mB z5qU7+C44Ka5qU5WCVVTb5qU5`CN!^MjmU$6GvQldjmU!mHQ`%fjmU$6HlYa)YeXIl zzzN?9YeXIl%n9ELYeXIl*a_bXYeXIl}D22Ll$ue-nRl_+TJI7yuMI2R4M?Db@&d2)|SQ&Vdi%cZ!_@ zA;RwzYXnAwi9-Cz;e!Da;albJ96%9%r`S25BK%JII|o>V$wc`H23&;SDRvIP2)`45 za`<3iM)+3zox=wMHo~YQ{^an%K#uUOutxY`fJgXN{GG!G13$vI!W!X&0U=?U5`X9L z!9bDlt*~?WU;s(@R#+o^Ft8*{Wx~$kg8?VuTVajx!9bMot*}P;V1P=P?u0eM2Lo5a zx566Xg8?n!TVajx!9bVrt*}P;U;s=QAcZx;2Lofmx566Xg8?()TVajx!9bcYhze_j z4+hwTZ-q6&2Lo@yx566Xg8?~VpcU2#9}Lt9-wJDl4+ijrZ-q4?4+i#xZxw3<`h-zg z`8x;xgx@KDav)Inonno^pzu58?;I!;ekcCq$b$hyVF*|398eT~r&uGvDEv@TKU(HFaPV0-~aXFU%t8j&>G6(Naz3l0B-m1Iz}1h{fGG(|H*g1fA`Zb{}zAdZG-&(;D1M#^2>kv>kt3OzyJQzk3awL*KauH{QbM{ z`R_lNE8hQ4zy858%pd;XueX}teEH{p{P@dvKm8Sv%L4Y(OZww~n{PIC|M{=KfBXym z$BPV!sbAVD0}+4WZCLd+O*2QJ|I07GeUEx(z9*gd`X2!d{_~gr^rwINM*rh~`khlz zZccxHfBEv|KmYRIe)#g={@)+L9RBv@pa1I*zyIrh{^74*{`$iY-~aX7?|%ON+n;{; z{@;H1jo-;iq88Uw;1S zZ(r8GZ0S2H=Py6~_|xBh{pIKHzx>L7`Rzab)9a_dz326v-s}IYDd9i=`=5W;DeV9D zwGz;q7p>YTHdwL2W^C})t#82VfA9jjpW6oO@e*{2UgM?fI^b6?c6Ni< z;5^?<`i%_~{T|;zM1tZ9Odnp_-VfypHWK7H{Nu-G9Pkp#sD^@cyfo4o>hm)XA|OuY z3D{&1HlXBrX#&Hc%S#0jb<~A57;!oRVW=mtz9|k(ZJ39K&t4EFD7kkC-V*TfP;J+laWG%5mY z*Lh7`dZTTBZ>B5Aiy&ixI||ffSfapS$#CA@^KRmRuL(;W;BNS}egHsu>B5h#&5Mh> z&fh?tlPvRlF>O&^{+U;BM?$uJFI`E6AF!-@0qz{d2HW=D+$->9VabQJE)Gu^s4mvr z+&h9F8HOX^0$SZyS0F4-OYh;Z&Wf)0Vk+aj>u!1iE5R3|$La~76kaKH?g(LlExk9h zMaxV6M+<-ee+fXw3irjd$5#?6+yssZi2i%xqYc==y}%PG z3F?po$`gM0N(mD))G@;0`aa&KGS0A$=g&_j6xtgQ%1Z}g)c~rHr{3Q{b^}7;qIY06 z2N}`wYy$|F1;T-?;RU#d3yGKD4QiJllIh$HR2uH@^X)#pUA&;M-v{Oy#mL_k4FbVL;a0L;z+uRkY&Rsgic zAV*Ixorl-w&)i&C+Wh>FF`oa~c>cB&gnss=qipbqFHuTzro^;J+oF@GIK;N-e8ct2 zFINfK8KGQW+%7o-Tpt_-2|qGW2AC%w0x~Z8F$L6*uR@T;Vg3BXgh2{H4B*G)8H{Qy z0BnReU&=rZ#s~tGg}Dsuy&Wo(fyqaK48nah0M~pk-AF_oSS>J49mo^lAXCNQb2E^S z03MA%6o83FeorO99EAf8x&j)aVJd;;z4DLghBEN_*#O6jJ0x|47y!foAcU6y;sX@} zeEbhOO#+NJz<5AMB)LfJ z9#U8=Ko|Sw_P~S!TNHA2PCB3w4jYtUc>BTLc_;`Q9Aw19yn}pG^Oz8n0Y#d2k46r< zLkeY1*v83-t1pc6CDG%@=Z5wrz65=I(am$Z3YOsBq>nKg;?4rri#M7f&u)+p8J}&y z%2;=d*#d4%#H8-cEQHPEtrum0=~tj}}{4Ds}f z6>8k!u~dRquX7W`!NG7skDCCHXJ_*VDjWbQsF((to$Za;S-y^bd;^eV zyd(f1D3#9B(I;VX#Fr=KbMJnT9|37`0Zp+OL`mjmFeaE@;(}KM6vuHq0^y9HGwa+D z%KT7PXzWq*QGC-1usXaX##OB_VVyB{$@6E7U`s{K&PDs4J0?122%`8}%jFUFY1thX z-!f$`lE+6-KR@wsf@K6%Gory*@o;IyLpwr*H;!Ebqx4uNaH|hrwCaIsgpv$o z1c)m}c?K)R(Q1mL%ro_D1Z4o7(YjCLQOjWs8*c>7G<^=yGS!xXYWOf{S!NQ4DSGtMywDGD_> zB@sL?5;AjO+XiK;T5X`3sC%}ayC!Ozz|IUc8eyxd(TGSMQD$Y3id)R0uj)Jw+2NR)>I6Xo~moKRZM>;*)-|O|>%rY%gWEvB2gqQcH|R#K&)x!kJySWq>$6h4CHVUq1#qJtYlz zd?6SKb97cBK+OVoAv{zPXoUc~HIC085ukkjfdW9|H5CL#?P5T@0Z8sy7jttTqj8~khtx7sHVpP!Y0gy8Du zpV=7p4jsw2r_IlASHE07x?CNtj{)7-J+B z35q!aAk{oVCCEI0AYh=Bw@mG01VDoM#QZS2tJbr!=4k!l(FInUOZ3{*|U^x@#y{(isUQH_RDDgNADM@+H~=Wdp!OGI4ZY4UnNTy<;VF5}cu7 zvs~>!e?RjEGzXWaX_x?2LiDYApNN&+VA}?^7K~@GUBU~~2o^ukvW#1T&TFB2JJdFT zJt2u)7#(3$L*sOWtyJixOCl8pTYFSP@vSU^(%!Q{vtxiC^inARbN zqszO&)6Gk_CMe_a2!x`loB&vj69`+=@hrCf*cQinAm$?V^A9r@X?=b#ToRu@#scyA zM;Z$>Enq9c%0v~ZfE$uaeAVMDh+v{Z)X<>DXRlnsl02Ue)ojRyWX{=fm>n4=@StIl zi3jh?pwTDV;-P0v%KO+W`(kKVyQ}6D6=?Vyzyh9>4?*$dss8 z-7C=1AlEaI4HK{7($styumD%JR^L>do6Z2>BohWu@DpT4oTamlY{!Aj@CfW789Y_i z0`UY2a<)E!fuOU^H(*Ob@zTl(q9h0lj8qb|-M~%?s|mslII9OSHk2E*9)TAw5urf7 zt`7^W(DX^?aiBmT)e>^z^D&(iSzIvGH8lvzD)P%E;gt!TM-usMXj!5E>utcUfKjm+ zIZtLvpa^e?S4PS6KE|vNQNIm}M)wYUZOFbrHmHSBrW_avK!YD_*L!!95?F|hD@d^< zBWOxitO%NMvSJHD0~fb9K*bI$%uIj~3l|Wb zbhZfFAs}!3==0l;dMMuhNcB+j@!N_pyg#}Eq(ESs(DZy5AbrySwjRtLQ1G+2^A9u_ zfN;+9EWtqCc>gu^$^8!WeYzaGoIuKYmq7jO0oO!_1mxl7&T~ zh&S&m()je_Bz<1KABT9glKbP=z<>YnM~eIH&+p5={NvxD=DuLtTR@CK(y3Np+DDm* zHh%oR=z}$cJ>b{q2W((Nv|^;_2O%7!I&MqMPu3N_#Rg&)WJ&e`)jb#@az7_z(7lfU z77^oWgLQQV65TMunLGdD3HyeCo2DVdxPlDOAmE)T>5LJ?sinnOz9olKU}Z(R}#-)Wi_x72&xe>=U^|?3Xeu8R)8;;k%*fKHDpWpw32evr`L8BSS19kH|yB8 z^+K}Jvcf)1Ooi-Qu+zbK3ustDH@McfkZ_Re?B%-j$qE@sxVMEZnRB+Hf}Vm1Xdx!9 zPa)AHbb}~u+Tg$rM!aQi2$vLhNK6Dy{!@wF%WO&e^Q{+HZOaJf{9aC1DtY0OL{ki& z=8g$0PZc2n5AZc-cEiMkPvi$%Fv2#+9mN8Qr;dC7Rp91S={0%P*pyU{ah* zwL6%dmoQn`sb4`yrv?hIIB=kG8mQJ3-HVs#^Rsc^7$+T|t)=S)9Bb1>?%E3{+0zry z1zKy1hFYBo1Lf1NoE>V~umUESI6&SAiT#if`H$ZaKAyd7Nj(3RbEAXXdp-XZsQJ3l zJfz-h#N0PF-@hFv#tT5g3tGonRB)=65%|?GPP6VV`22A4+Rh$*OH-J(JAfGWH}vWy2}sqhCs1@NG(m@|k20wz;fhBql;pV3ATQPkwnUT>*ePd`TLNR! zEh+`YP=T>MD53K=B|^0Uce_X&Vh1n3CXlD6 z)+-~0gLEBl#=Hh{?nO)_<+rm+i1BfPpkiTmGS>KbIjELTml?d2NjgCofK85KF=YT2 z{xH(MJpsU>;Wbae>zRZ?|=7M8==!P#0|*?vn=SWO*b~MI)fq;@p0utLyv#|2gFv1TV7Xu?O^$>-X`Lug{<=p%n?U@hEE0DQ zpc|wP4*tFB_q$PfXe38&iUSl40?pC+eEBJHTbJLXBVDfwF1qMi~Cl9ST5o zX45jeRm(E@Vln(d096$T;SWQB(I9XWc>lRfTDQ~hDDf`HoK@^O0rcJa*RLw)7 z@mjOR#mk~(90rKIvV;{5Lm=gmOt65-VKQzi1QYxH0R?C19&Xr$g-?BjJXkJ3T-=c`f#Uji|g0600+g4?WYYcy2uDY%KvR1Hg#RM`7 zNc%?HFzKj`*pQ%+Rl3}^-fwscB*Rm`2x4NML5xzgW0^UAOEgjkOku3IMGrbeSX4-C zl?YxorEVDzl}9&7AD&5N-a%el_q)e3Pg)PE<-=9WUN}Xom6hw(1X^DrLiLmjl0+~+ zoj-+o#nb>OE$mR7Kfr*p<+U?L5LB&11OXHXxt$xKz65%w!ws1^&M-z$4!BeyQzdK= zCR7kN-mwo76`3l!Qqha2gaNc)IduCU7-j$(Ywt&m@d!=^YNuPbcmb7q`G3bm!FdnW z30yOc6BGBeg5P!Z0fX~~Crkn=t}}oP!THrJkRCy$^uK8+F%fJMBQ-Zx^dc&vht_mi zpsbTYw5H4pO!IjgIS&#OQGQ|1U_e@nmr>DA{?afNxUTr|&>F=b7`BQi?&!WoxLauC z^Du&e>*K=Irnmesv82Rjcjm}Uv`ihV3V;Li?a6qi?A$UEN^C(p@c+Xo0Ni5sXtUBe3L;pBJyI!cK)MK=AcE zM42g=PNjySOaKP$4Ft<9835*+oIsPn%8^Ea_y-;VrajOod`U+=4RY_7F$h!#u65*O z$r*uCXd@Y9cp_E7d~EQ5sAS4PqW6%ftN=8tMXSot(HlX>je?})m%tqMb&?qM64s@A zHiR4zc?lcE^5%+VFR-HbFC*OjbNUD?WLQ{-I3a+RRaWmxk(D`z$c85Xp<7Hb{Ii- zuvhARu$bL}ecRi$ObwA0y#fGSdErJTg-w$*dE-;YSh(pCv{no)u@zY1aD>u2v(jgj zh+hoTIkR|f!ciK6D@+itym7y`j`T|`oz*RH{MUO{xLYO}p@qfZg3kp5kjiT|LTQ;; zJuN!!zz9?SgQU_kG4=6ODbkd4Rvi6j=Dw5}vCgcGivu?est+cAfvW=4oDtCDAELu5b!q*;DL&iLjVr)Mq$a2WvH{L6^Ee|R48b*jSXEEmBs8^D}tR_b0Uq5 zgkW!SY%dLEmSTfo*VW=_0*o*Yu_Et)MH3S-6Ac@}EX5U6B{DK#>k0-zb0tW0_U^Ho zW!bi~Y&)zC{N_1qP>$SWgUk~%(ve%cHsD^xrNwXt0D6~BTS`FCky{#N<;cDW!g)7L zYpAjmBM8PXR>6n}16}?S5_YP@-BpPVSr&=438ES80_c=$G|KJvILXVh2#1u75LIFr zVW=w6&sBF{B|;r`36V7e%>&_##0yFk{F|-QzKwCsp*o3x;IgAH6pIZa9tfDVK^`zv zJYc41&%20oE-w%YCE-{LguteaR3Ws_ySy5UZXD@386MCn$tR@8FxvEB**N&z+zQ^S zu~Z`zo)`wr_gOrsjA6+5my?Un(`}o)91C)n8KN1wZ6sRCB_hHwx@}-`P^q#Ou!W*5 zu<5{U29|<)1I!3HFX#rk`@^OihtZHES-d7oJb{h#g_B?qPe2FIVAwl{q7(~o&EtS+ zUX&#)5RJ3II6JqY<22688@?z@7sbt<$%^3wq7qd>ASamlx8!NCMCWgyAaU5ZT11wY zW~q-L57dw91_MphKM@LTd00&VOmPR;Ek8K2Mi&sJ{sCEcC_ul`$yY*;@F_~QGS0EQQvlQ^a?G3-H$!%3_26lPHZsFo>evC+a5f7ftDF8 zB5gu`2cjLHwR;u@XQ+2@?(fr$lTn~?rE;-BP~*(nG)+2d5stg}O1YHET(~kybf5z- z(4xzg^v9sc%Ka4bVyK`9hc4OChDBd2a>kQ1N(N{k%CN7fbr@onQM#sS2DR?)7raW# z3?_4;Knf!W$`8&j4_JpWLYr>ci?qxf`);~)E(6sWuAo&X@Z%6~;|kzZ7boerc#)QB z1Ty0WND=pf5C)u{^hx?h>)!2S;{HF``+tBnE9K1et z3xHXVyZ`&vT{7p35Sr9g09R&QwjgY)BOErQ-j~P48C$txm zZljNazq|K_>8=WzH}4!~xOfQKW; zfBM_6zx@3DmtVj8?e}kQZ$PljB?QS0nS@XcP+FxhfM6K?bO}!e_@o7FVOT9t=7`k- zUA4@Q7WkwIY+V>8NQfJYAS_Iv>!tJPrC)wB!F}r9bOU>_BE5-SX%Q%HV%D~SN!-{= ziebB-IN(qDShX`jTipmPc`cS5`kzdnN_C{2%E4+S>E4&Fd0Try96Y@PWrX?kOgPDF zv0#8xcN*mt)Xy)T^`jSlw5QL1ANOJbkopFsu9>Jw2!#wN65>o0q$ubsA3pg(nH2bR z=qHC_(6hlfS3_QP zMIT>3{xT$rpZ-wOLdyh}z>yi}C;shR`mjc3FvJcm0$>7)*^L0vQ~b+yKs)?-#g%Y? z0>_sF%)>1c8!ljL!Ri9!KuPme9~f$tXk}{?EXc+Q$`goUxWvG|YT>6CSZJRb55SHH z;{n{r>yh0~WZ$01DVFe#Q#YB$S>hZwsv1P?Cf!4qDqo0Y{uel&FxwW>f|X zfb1P!)v=yJ^Eyeu5oZMu1-F<)2@Aj~gk2shEHEWvQe>6~$;+%j6@+N5!axZN(qPi^ zV5qQwgdpcB25ptR)=F5R=1DLHGh3IT@+9z>H-duC7}Vs&R$$xBgm_?;GCv~x{6KC9 z3-r?c>x={=-kbp5CHoX?)hH`~wEF50&_G?BDvjk3a2j9*11|t?Zi8d7LTL9cnM3!^ zlT$Bygs0xAK84m|HF>#}aEL?$fiXYi5V!UWLzV6&mA_^(Df&;V(}HpN_T!hmZ{zz?5;ClWzP z43Zxb=g&}yp(!_m4yUsM6IZMtdQ4RK5OZhvgcaDS5gOAx1oM%)$OiL~lt)cGNMbxv zxmaMhv|F?ed_4~OQcWZ}BZo_lUTdWqfsk;qh9Qk)osrCnc=ducdCZPlE~$y6ad3xg ztPbo;D1vMOz)T6&7XcE7xYm&k_6FVtwK?YrRgkWPg9LrL)K)`FeD=3YPnVXuYWL}lWcN!5p;HvwhBhQUTcTOL+b#xhzZd)!Vi&}g;g z1zusLdO_K;RW}%De!{h$6P{bla@_9gv&kz zyK}DI5D_uFVW5a88G)T&=01soqn0};CIr1j#Dsz9EznqLj*l7|E5#qQf7k2;yj~6p zmlT6NtvD`0GJEFodkjWwDsOJmk}BODz2DamDCVfp%%!xlnm2! zsslMD3ut)doG*s1YZNLlsHBQueYcakDDN1fQh11rfyS8Jg&VJ6wp_4W>{+3~}A{g2MqwN`Cma~oPJ z=tQhg1TIh`ugsiR_A4v6J;77^>5>~J*f4`j2Ovm{BSZeIEHfSxB8Y(LJfSu+rykNbk4D|IN zUeMYm?Y1af!+lPdp&BV8S)0vx!_E%i}A5& z0MpS89qxk#N;SX&5G=BToHg`QsD*UJ0GrEvqSd}4GPY1eaKZ`qVK?ex4@QW&adWBI z&`%-c9dLT(P#_Z69f%Emr9uHOqL&-?2P51No2JSfPugZg9>U36kwQJ=qwEbFa`82E z23t2sWMcy@R`YVz6o;^Tx~iZ!Lrn=F4-+OCB_rt5bHcZ|agkS05jD8NfttljG}+7g znqYSsCo5nBZd4#;aj(GFhQ$+@k=LqAFv4Lo9_N5nIm!~$VriF%f1Rca@!U68Tof@1LXUJM2y}yI70W|3xUAcGQ%S6QF zK%CMQ+#5wH)}IvC90m3yLu=B4gxR^#S*#5#{;-zH;0ksD)1y;ho;n@9m&!RHfHHYI zlnLdp%ZsH~sFgCkLV{L(ph{UZz_iQ854?!VTDoQF1n5Lb-SUOvi0I=xI#GJ?gZogc z)h~Mim9Ri$gkpe!GD7q7`{FQOK$Ha-;E=%BIAuZ80RAKe188+Zt2k}chKZE0(K4!4 zgh#LQE~(_hnN;91fmcoeq5GP}=|J|IU=A1TZU>V@v&gAZ?fbEjQo_gVwY67OmKy^cLbm3A3O3cn3p}c|?A+++lDG9<8Bo6@(a`l86 zEM}T|w?S!=T5ENH<<kt>Vj>|dSQ7+@5Uszab&yEd zKFew7q`(2E-HAkE)FP(?Jt_WAkk%WeMb_}NA;X@$R7xsFsL>G0pPfo#sA$+Gf%AGP z=_D(%KTun=i5L|lOcEofZP@z}NqB0M@9L<1z0Ww%l?KRT=q#tYgR%qr*rD8^4Kso8 z@DoOm3j4tohG+qSb7ldRYd$+KlS_%%rhtQ_!5M)i^8tT&EE5v-@xo4Nps4{B61RFV zf0^N#7fu1FO;f<6AYuaZLmKU&LIPA*^o&MaaP_(=VS_q4;8+bY+Mz}V3_20yHrqw5 z$r{ce#6=E^S$J4u6uus*O5nf@XD|pv*n6xIm>rQ1WrG7Q$PB$4%L2^5aRqAuKS;bS zpuDh)6O@8kGSm{*8YVBGBc+?o=a2}yrGEu?NX)}z%}+`=xQEHTgO6gE3iyawnlpl3 zGV@cHD+qhE^6%Rf1{)_gND!$X{4>ZF&<~$BGP{CQsc9tOyBK86KJSEs-G&2OCvG~? zp)M5WL`cLfBaT=(YvD2o5)t}NV0bn&+A?uV3l$QX5EZ3^2e2V0aY}fW%IQoaEEckk zl4r;TvFv=IzJsz@KzNtZ85@u%hJdAGf{W|z%j}oH(RdTw&maorcm@Mi%HRxuTO1B< zv3g0B`VKTpqB`7Iv@TEvs!HS(a)iE7M$j(=VBX z=mIiqZ-n9wynu~*s=5Oh)qU28bBdX3#kY52(>=UY!lk1sUA}chG zuo$Ru)c63tpAD)T`bHSFhUgd;x&{5R@xWG!3#+y@pRVBx;(Owlk6Cm+Rp>q>$`$ks zW`4PGqSsf^&;4R(0!ap~q9~3a0o3&xcdew!&V8X^P!>k2i?x9tCldZI=?t-00HYqO zcUYuUH+F7t`O#3G$0Ic2}(4iX=1w;n?}^PSjhLD5sDF- zDod-EQ_+XsDWFsm3ZSbqCQ`%97WUe@5hM2CgB@7n?&yA2+}k_^bqW&=6%aJi04KdF z4Ty`{Jnw0U5)qCIhRVqfmA#&d?lWec@NO6bZi{-i1X=RZy%7`^b+^>2kG!JF%B>2Y z`_7NxkT$qaHe@G8N|0E=b6=?+bk4Ag=z}5hT_dgp$r(JOf+Pw*{@y zm}_Ol1KMUgM)PtiY$o9UQ>n<(5p-I_1C@$%@BP9Z5RkdnecyDF8;7;RH>A@Z<}r#9Hhp>jt-cOnY6H# zcL0nfqj2IK%n(6c>nIcD8E#OwbM~?-9J0aq!!-2-tjZY^oXc=Mz<&c+^_;pXmY4M} z2k-LlsnBx6Ky8qkGiA`0<|P0+;+jo@d-q%&V~`t&2<%q~n7vd84_1&jPAp+DVD9Fjwnqp7vmbTqAt$DcGSR zhZ_@nm5-SsVb0M(KsA~O=1Y4&+xG`6-1|nEq0u#Xg%#faNp&DDBneFcP&;(-oJnK5 z7qTxgfsTQ$!A;k3bQ2hh4I(>)4aUk27yu){Zpf-{D9IkT4Ar5B+ud_0PO+EP8m$4FvcqVP5#m00(By5{$FSVji zed?%&-5vH`(XjQY^x$-9?tJOgI$2lK{z`_}zXMRl`)ISiU7 zmmwR1D+gB#R1yKqS*Vgu^f|@>=45OZ_$&uwXJl#$#u&D%SIF#<;I$;yBeEFiBYP>8 z+!_|DEWpdjf|tGO%E}G68t6Fm1EC0S7GIBZ?5NdKgFr&=L!w^6@p?elOr>fef&_F zp*>V;=&yt?6tbKRz^XLLhRO_|@CI8fMnDL%oQ<@&valM6EQcDQ?GAPw9fgv>33QM- zJ*rR|=nA}{LPCD~OiYXu@JI^-9f7wIO0+2AD=n1Hdqz?sV#z?U>{_OV4$BVtg_vYRjYtJD{F4LKNBsCOfg2w*R9M0U zg$F=by=`TRG!PHKaxz9aU76faVJWUqJLlpGL)Ay^J$yrkB_4w6BhdsQ(1c*ySoKj; zj|UlIn-+=@R3A+Q0uWy}N@pB(Dl#K86e!;eK@3|IlN&cF)IzXUb0gBlLT?frkF)nV zQbBDJ4!i=#O0u^$D3HaXz#;hFj$Xq^(*yQGKo)ISv}Iz2>oGu7og6k8h;14LjtNPg z$r`~His1}FDhb~VqZCSnkp_zUbYKJrT0HD=OBkWHjU^%s)i&-xb9M{O@p>%P9f}x9 zb%&wENKmM90#!i0KNA*p;-{Oxuz^G!ucaF}#>0*wazk^x?loD$8)%;=QRziU7^;14 za!(6Y;1VPavmo!4DhEktwU0wl?9Fw8{i8 z&!W+ZUP8@~Alxr-IYVX0_6e-lXIVqc^cE+f%>aYJ+Hn|hlFzgafO9|L3^g|tXBa9s zpjZc{-%ZuLLQ6PPB7v$O@g+ zjSp6cu+TpI^13Y)jGI=EQ8>=RDGA!%m(FL?3ay2#7j6kF)Ud$C_yIJduhm1#2nT{4 zhnu!~;TBzbE&L}nER_4V(ZT}w&CTS=%}cjLRD?Ge~8XPw%oSERbdGVI8 zLQLLu1hqjk)!F2|WrY)v!f6sE2qarM7LVZI?GV9OT!iY}XIZ)-5P7gdq=+WA9Y~_J z!cOIwdDU)!f82hJ6&H}W<@U=&M{$n3z8Wh?@uEAlu0|+UsKK#V zVXWYIK)XjWbHUM{U4CbDKEg6GxE-qgV5wS`j7YxUAb#oc~@DvKsnC}`0awZ~RfJxe~ zarUC#@yK8Ir1|GRKTp6s059WGKYzJ-5sQp2pZYp^@t+@dYDZ2DvaRs~GU?)cPt-ob z1(Ye7sCC{r*CC4SoV|=oeFH@i8k)6v>hB!*;Sq!dtdNb;+$W+yjFvSzxWKdwHbO$t z$pAPvx7%D+z2($aFw_Q4EdHwwpiLDI7_$ zP(mi%gK}>ET@(&ap}B2cWa~l_2ABgd2%y=)>TNU&2z`ndVLrN7_{*U{1X2wNo6XC& zY@9YB-NB52^H=^IM#v=H-Gsx31D9MDzzqSb-sx!d#06xsBFC;5?C&3e$RQqNcJ{Fl zIn9G;DUo<9tVlOyM2^mUa07^lm>dj+$N_o^mfPh9FX6&l$X2N1R6af36JE1Y2pMd6wBuKQr2I-cXXW=NAHvAz+g%~MER2XWc{E47oi^X^e_vnNT zQwa)vF@`);%Vl)bBuNlZ{}X|6;npdk^Pzyq46(CYr-lt$90|Jd_BP1Q5UYi7hOt%) z=vt8++^)^bxKwW_oNCn@hQi{s{lV+Fh;bKU^Eyt2xsqEKecjVI^`T@`Ojw|y2FPyG zqnB{01}O8?1x47*MBUdw)mngi26xUNN+c5wmclRLcz;a1`&Tb2cyD60Q&(bhtui9rS|@@+d`a z0L7q73bsm&XP~jF+UM#CeYMXG6C4cGoC$1^7$%6hsytyVA}yR?exGi?0v`Pnc~P`k z0`AKXZW=9g|EAt!!Cf0QXf`*m*8+wqOW;PMpze7vR({>VH*VpXlDcOgkS-#hAE45x zhNM`6tlb3dFyNc+VcG#u^@xLpR12?wx1ZT^#K@mTJ0#M<1ZfaPeqI2)%ZSUEaM)05 zLG1I7Y&jvl+o#Tu2i^t%N#Dt-ziwWxCBX-B@c^P_Of=6d@J4DG*|gccyO(N#?BG7+ zLd=Uhg^vX7Xg=iPF^r&#u4b8?^K1j6tq-dO${;mCkf9^4&L*i3eh}4>x&+rIc$t=P zg9Tl?mF-%%!NMlK|87w>XnBE`Xwm0ix%CSyX5xs0V~uf!hwJ-zyB5jIv(%4YMu&-; z6-EZb3=X+pYyi-_G>bxjZhE6ZN?bZ;Jx2+nkJ2DA_8P_*MWwH zx@GpWV=v1Reh@>$NQDCp4V!M@M}}xmq)EZ>t_5f@Zn5WKY5|Q&z}q;zvdzn~pk;x4 zCv*lyvTb3bbcpU?oMqy?gSI(bS?pC=stKYj=431Bs(%iHpsNUY12;Lk*0? za&a&@lS>SyR`wZR@VYDul8r0>2?RQMp_q6G6YL<%5DUe-KSHFQQHi6t@Ukq6Hpm(rZE;Nepux7SQhapt4}IQT?>@LLn(DFZ<3VKf2P~->tOF; zR8+>sjR)Xs!*~D%YE~aWUr;k|0N){b4VH)iGY1MgJBEk=bCTYBHz4FE1AOiY_+@f= z0(X~;1W$Kh5hmnGESqU;Z>t-(E{3v6|p{&o5D^xgMge){pJzy12l&)%%Fnc*qvR|GpQ zrqlUV+_HH>dQ@NFP?QmvJkXqS9gvAOkA;e3kcZH| z`}B15*pR~d4Ak@g@pD-!qd@*5q7wOgyB_km?aO)bQa`VC)GwHE;g}?kZ;c>vzOuY~dKiMERUX9h9^toI}T;YQuA0Pk?hV%MZ8OdJ+ zkb_6Dc5?##WPlr{WBV?2g6-!gB>>O*kQ2-_C@WY6@?my@erSfDK7ZWxBo2F$$%_mT ztPzS698j=Nz!X+klK^SJ9>%@j-U|)?lMz0F)q;1{e*W?ZYK6!s?x2(yDjk5-p#wJy zDJ8tmL;|oXVwqc^$hlbBA3L1ub1yR}{|Fj5joq`(ui*wX2;$q0TyRh;@7EBeQ8O9X zSv+{pI~hc$l<^uQgK;{gwXu%Tb;>84KyA{F_U)>3PiR!f>5>Qn3}Ov#mrBQ5pcF*A z2x7xJ#rT?9>Fh-e-erP@>Hx*PbAkH#XR*Z{Uq3$`^Vz)z+*4S)jFF^@34+xDN*bsR zFisj+-u9|*_x$ql0CuAP&fX>^=0?n|cVgmkb^iiBvy$CCw|qQ-ox5IvcJBzdAB>Tg zURKgi0U+kajTc}ih4lq!c1$}QArP~%r0P5ger6xLdp`O4^Jj6Oz9D7UA|5~~Jf+@K zKrw*b$nUc)1kpt1oHJ#YR~eK<3C9v)AE*ra#Oh>c)ZsG0K`ErbcZUHObWhDnh6)4C zo7UZv%BQe_CPOewQUPI;{bL8Q2gg?Du^@tB^Qv|C#PSJBu!A9SjEEr76*Og_5fS(V zdLuU<@x=170CLD*+X4W*U=s$KlwtwDm}VPlqd{08CPd-~q@NyVLe!)^k=U4vhv5ZU zm9Qm{7ifBXAZOf-y24{!RPY)8u5st%G%S$4AbNxFf{}WIW+3pjVR3^xBVvJi!YVn? zkO;Km`99pjz!S?yHc&&9tD}+)#;T4`n`L5dNRal$*N7z=#O^S1;yAlQG6Me?Ry@h) zd?Ff9Oy6xni3UTp2`l9KhFgF4yz)^NY+4`^1t40?NpaH_z4xt2X_Nq1Ip&+)v&wVO z%z|j4H7e7Rm1IbvG}g4Fs^t4@4;EHq0V*+M}7Y_j>i6$pQ zO%0mhDs2ZpV+87A3C<)D2MbrkD0S-k!!L0WB!2?LE0WPp=jZl>m` z{gc0BpPL4}>Z&1v$Z59|^ zKlzDvGEHJe!6>Nm^usOwK#NdpuuU5hJVvB%_ayTbh9V#?40)(WwGVAJu#dj0)HciuOUAh&Dfmn#@O&wSF!;&ET;>1Gc)IU0xz&f9yB31#O( z$0PX-_YUlU@#|?n14Z5gVy>)W91+tm9Nb2-_88C8P>6A(S)JcObG=TjLL zH&C?zLUAlNV2pwlT*u&f=U12wHn9C+g-yKk!1~6r!b0AMAwnWN1dJD5sR-i0bPX|DJTzKlEv;=F=Np6tzzW@i_)Azwhvq3p zmkF4OGlGaUDHp%aQb6m$KRnhfWk!>TlG^!$Ef#t9n+8dms+|zh!oR*=8WW@m2`fhNy*{<{2UH_WY@Lv}fQ7iX4*JmwcWy{%b0nwD!Tp-c4KsOA zR~#^)olK)=liVC!6HQx zzg)HG>F7l^3z1GtSHZu%5(#pw>1w-L^qlnhEpQ$yTEvt2dfmLyMWJ^vfNs1rDL@kqddxbPfwsG)Yv{Z9K>|4HJgi#<$TaEr$Br2zkc>o_Q%ofJXq? zn%k3(-sxZqzQO23M4^w^wm8s<1U=#5KRcD=c-?5AE>@_EQBKx znsRpWE09k5hcxw`A4+U&&y_q~{i?Qs5o5jkQa`zUjC1y-WB9k7G<&l8FhB5m55n_0rT{0QL0WQJHdXwM>|s8w%3w8Fy>MP=M(W8v^ew)+3`Z@>QV!*a1+oExmwA`~%X%k8!qf6CM(y(gDr0e@_CJ#H|BtPJUR`ST?50 zrzBY74wR?B2^kJC(jDk}Dm9p(pi2c)C&>!AZ$6~K0b)%^H5q~EaCCp$P{3O2#fAK3 z8py+|u~Z`ze*oA{8$Fmm@Rxogsq?&&7b?}fggQ}~K&mi9h^dlj#-L*Ayo)YnLUW*U zG$dK%{2HhfX0bX@VFx(~0WlqPV!W8ld{O$Qjh7%JY*6Ryj3SjTw0?j~g^1b967s2U zh?f9315}A~2VXO?lAk#Tiu9nNk_aTmN)P-P8ME5-VE56rQXoC7nzlnPHz6#p{BSL! zj9DQLVf$qBgB>tR6CM6#5&|f9fK6YKYYZ5>k!E<>%6~mQ3I?8FqJkG`sWza0pgsbem!PQG%u0=+eh3GGgLR?jH-oV#9jehifTSjO`Mz7ft zMhHfsnei%a(HAFi%LdIx(#y7lH`MGgXnlMNxs&AFW798}BLS?N(s`zH)G_R#kvnG|g1n#H$qU5Q4|T?q74EmYMB zGjeC6_$eC{rDxe-6L763rROIT#5-s$=Cx(F@8I?ZB?r-m%t$#QbUapaX!ns`#-)aY zBL1FFAH*lrm8@awB{cg;uj3LCp=O8T4P#}8CcvH2?=${TdIyNst_)kDe(Xlr>+vDf zn9u+x9A3$#g8W&_F3jSDcfTkY1#?bwFT&^E3cxt6#2>dS_8CaTC?7=AKB0;`Utm>q z3^h;_i3zO27c9e{GC`@6mT3aj%0y+LItdd1@plOS!^^o;S123l>Iyw=q@O&YqPpL% zMuHp1)d%4SWzI|^$r=Vn=xWZ~vcUFs^Hs0qG8YR3keP@`#oQN=x%K&zh{en-$?Ld; z69}NE&S|~?ZE`L*PMzG&1{SfXqt982$6)}52Rp;GaSQ-Ec?*|LPAE1Y<$ay`uN*gkJ~||4hHkvb_&dQOK1G2% zAYz-kgIC`j%EC*uU<9;oZr!Fu+7vJdPGk?MKA(FpFuW%t{XWBk`vltPVIE?K~vhrE!yG_wWKO)dn#z3mXiyS@*jW+Fkbs z5U#tC1Z7wT|2kK#V-3q@4qKfYcxe{+L$e7g;EFyWX-F{APQ7u?cz9`+8E$FXfv*@F zwMu#g17U2MTsRDYoF~WzP>M1rfGbcqR5$}Abvn+l3@q{n=lJF}NK8IVG^jQxvjQk2 zu!(48C$4t}q1HX2mA%{!X|pp!jufsnXTduw(kpSdqk-8tS+Pm_pqj_L18k5k;me9I zTzq{G(Z(5?K>`Eug~J{40Y75{^~_wUs5;UBkx=@Ydv6u);;5I0oy{eC~QGj_iL@EuqRYrlN%p+b(Te&Wg5#^C@yT*RVs|NP&@&go$e)gb(S!~ z&YANCJwg~E^GOadM-tp@MyF@CFToazdj6M=x(nE7VVrg;NDKuwI%bB-vkQ&8Ef>QI z6>uc3G*oT6qE2iDg=6D6Y}Oxay%;inH7HOoAayxdP-u~Wz@BW=L)9{bP?VwquHtM2 zjQ>i#7fVqotY~|3foN6?yR8`Y63_?z8WdK(7IolIL1867tUf>3sbW~61_f@nkUAbK zC?Htg!QvDKf&PU#>{Iqd zzEUjlAlxD1!ND4O5O-+C179VE0m`zi8eo`Z+uSsOuMi_66ew00U?eD3+XS{eoT&?P z5(JOB0?1{kp0C%&Ia?$Wv^lY8159yLjZipG76z)hT#@|g5Tm4UiJ`hi4%4xM+dO(bmasydFEd?SAVnB! zzzo0+hBUW(^m;6^LUxFfAF6iSKv3Nr9#J1y974@2vMfA(pa+#LPtznMj|Y1UiN#a0 zizhG35|8016wC1#R6h2@xBiqQw1Lb|p&1=*$ry2=c26Zb4%Iyo7*#Tu#=$GIR3qRA z7nMbn3&X6U^$>Rbavh}CWszc?=w9l^1!6P^mWGGH)8fc=@hH80TmTH8UsA%KDNOl~k7C~WYVzs<3 z%K}4M%20ONNY>V&WjNGA9u0H}`I+qCby*Y>E`c|rP7v$5z?&o03GKk>g<0Yy?1gGO zUP50~+fT((Y#`YibKm0n2kte@Tp^x9ocb+1g#-SJq2^1*}OnYm|#KmoBwh}@Ruj>fxI73=WarR zw*iO*Pzh$pc6xo5l{qVV79U&aQE>eRG?uS>(xccPjG&1E6BTy@D~)^O2J!jV6y^40;+}NF|nZ=n9{@NFXx{P16bH1Vmu5G_`r7{fdArkf#)755CB+wo6hlU2(rZI zXYX=>Z8)9s(jnx^RhzBj8wij|RmL*uMI8)9F=MWCX^CkrZ|FI95t*E?-YC!4d|bFYErZOVn0xp&M1-M?c8X5NZ@JaD95^70!I&0#Q9s zOu$XU2C2?iCTPjMpZt(bR!ra#CF{$+5i*REl7O$NCRU_8+2ao33p@n=ag_ln&)I;b z+Dcg@8(bs<#l;P}QQ4pyA^=+;^YIg)q~zu$UUnrF8$iY@(#(&<{j(Az=aUSLy5Wv& zSz+f8es_hk7hZ{wkYa*bLP8p1f?5jYCL_Y>g;(lRK(8<{K2D5~#4XHt8pKxT5uw_k z0Yf>x?n<=*W22R7D$z8o+y%n2kM?!%K_QIL!l9gAcBSTq#D|AXC25qz-hE|$vaj9O zNgAR`sgTvuX;w?8*IlVbC<}$ik0UJ(rzWL#~F57%DY1ng%buQY{dpv=S4C8l{0bSY5g7 zwO6VM=$_Ff%Tq*%*#~N#`S_f_yE4&huW;PU?40;lX6o>?(lDrb9%rU5c3BWOhs})k zq$PpeUm-wP%UnI7H30~mug96IV+GWVSrk2kE>17O5>`;-B<;?;WP*Y)H%{G9%(f;e zOvE6ab{;_^;9BUiYK!4|tl9<|uJa6#Zv~d-o`PLD$C@RuC(@__#5T~%SwW$JK{~w- zOSJ)mbq4A;1_^Fn;SgZr@4R~~b48*U=PYjb&KCJI-cZ0N)fOP*ei zr9K5l%AAD|5qCrwG-hMYx^>?^mbb88R125Q4}Q29yVtU7$e=tNVyJRygJ2RKaTgi= z0=jG)61!HBYsR*L|DCbQATuSaN^w&D*@#d!@Xf$wpkf>dv)&M^ zIlWFxH9(1q)d1r}#ijx5209F&HItCaVSpSXx<@MKRZG(VwnCHvfZmV_?x8ADO)r3M z0}WNr22$B;v((RDMyea@rUaMVKqFO#C!Rj<^wKOVEHIm(C=f_W>Gdl%k@e%%eN}Lu zE6fX%^~D@_o?f3NF+Jtjn-dLcWl&jKxBzL$CmiR|`_A>=Hp0TslEuwby+BJWnRK&r z36cj!X%kKneRC-4dmo32uJkHCn<7363ZcXoVFh5qpwxd;p`w_Pq(!^&&0m zk~zqvG2XKo;o4wcHd7+*`itM_xh@(?&| zW%2CdqE~5&J|W-n@!45EZJ13VVZVB}K@1a{O82LiX-QCvuF$3^L+0YB-nI^tA(^t}OWwfWb<&D*%|dxOQk}HFo3sa~ z7irO=an_+fV{}oj!)2duJt2#FExi}aIUES3*2pItgFf*=%I=ytSe%_ zse9n^-8!)%CNUW1hZ9)3a|hG((|Q>bz|zFQJW6^b##AANnLF zM(?yq)Kc6J1NBbQ?_$+JKa&_}@E!3UTdv%*>Q#YXv)0 z3<-4MQD&*YgGPXhjUqv3Eu9$QN%J^&(Ta=>KFQN-v_O4=*0nax;ISA&&rFo}><=_g zQ!o4XMq0H3gerYTZ_kC&iR z=&kol_*@{s4FiN7dJuz2@@g#$%Y}f>@b`@bD3kFfY)fr zcPmiG1y*(4z~lh>9|)_;co|R%_&jF>KUJg}m{~3aFUGo49SEx@UX0$iO)*J==no^f zVBiH>^b%wQ-FM}UL%#LXHN!Z>7(4|iWs#(GPr(+7(4)W_sVVzSEv%{gl$UP9Pzw_j zHUH~EXkg;czu@o5Xgy_jy*{dhd8Dw75fo-eL&_! zOaMZmLpSFQwo;6TAe~=K5D5~z+A# zyo7rJ%PF|DUHN(##^Ie;F!9TD47%lZF@cwmAeV}mu)!dugRh}t!Zu&9L71lDVsdJX z5HTS}YI&{>=h#>ywLP8hJ()`3@&YXa=IQb|_yptbbsRpy#@XxT)maewV)IT6EHN># z%Ok}^&}5VeW}>J7XFP#p5bl_8|LC7j5`q+KhN0S3iPSiGye3~Ph7AhUu9D+Mkv$OA zuF9muF9YBfr@DIxfnAQap;QP%B}axIfH7=xv?xUZxRo3=OGcWAG6`?c(gA={8fM|N zo{UpYGf%m^M2molQ)cA9C+xF^i^AyiG+}?jDSn->H@GD)FViw7z{?r6E9z;`nmPbQ zDqDTS*$Xr z;SPOKhdo)L;&y@MIR3QDtF_dZK%Jo3YPbVxv9GBcPX3k=68sR!r3bIqQjJgw1-Sz| z?am5?mJxPXxOX#3xV&DAjyR^=MVIWL5gP^8P}!k5ZNI!=3qg=uCXEho2M$GNu)G%| zN!TU1hwNqV_Vf}WM>g->E-%>tL#hW z_R$9S^=A`~AmLimJjeu-F5>Uy6NDR_HZf@HN}{4^g9aSo@`5eZ21V{xWx_6{LtXoH zBX`>{LKBambJoT~$hU1JH{c6%1~GPo&3QCIx%UIL2`uQRDL;Z#Ol81HfQzRxD25~} zB zL@&e=pI?{l8-ytw^AQ@^Fq0tmvwL=|PZ_`t3o*dNR4k^(r%sqC4n`Up`_rY%%dgbW zU(PvCKqnl;F){8*-TKJ^%CvN)M{;8VFTPTJpyG4@fw&I;=zpeAN= z`Vn5xl|)_30DfGIvWOWJgaHDOOpmnEISz&~f&9f~Lc~P82{x%(MqP*(B%~_&x~E3@ z=@FE=(9cS|01Mr~BG>_Zi0sNph0vZPz*gG?60I8^;U@zq6N0H|oh)5mfdw1vO8*)b z@Gnd->p%m>3joTUFupulAU^?a_s+yGn+@#DF!(~(k_~2t=Q4s==J(Xg(EP~=F)(O9 z1h2qC8L**0!hnFaftZ6eF=2CrV|4xuN;+(kfn8pFr9J~qPJj{AXCPAXsdrx}Mrhu$ zUS50!BTP_8Q5?f_BDPTG=)jT3Dv#S2Ta^DMF;*j#3VGHIpUA;Rs*sz^HI{{E)E$JnEVC=}rx7Rd;nwnJsXX)Bso%XK-bbmtI+zkYuu#Li$oE5;P~iSy@kc6gh70 zWr8;4nHN?;Oyxxy%)%-&mq-co+i5IaUQuN!P7wXlf)i|Xjsx{e zyn*%YBm~6a_lY=AR|zE!43!vH*uq!G7Jhk6m3RlWQz%9ls8iq_Kn3c?M_yGWVnLkl zF05BC*34a9sXdhjxmUsh{Nq6Bv;o!=?r0b!CJSiHT};6|hJJ3;8YVdQ_u)5u>4F(z?=#qCBzIfqm8oGOz*HlqaEFBrD!;3y~fxiXM>FRj-=?z3}*i>V^yrN1m zL6D&4tjJaSQ0*dsa$q*DOYnj!Tw}b503WD%B1+9^3Pa@sp*}4g87_CyB^;d3t=sqC zefjCfpZ@miFF$|(<=5|i`~BOpT=cUeFQt-Bh#t94lsxge&V2s!wR70CFjehlwdg;- zKhp9dD)r+tFvSFn&~{4Y3(}>ChI2;Q%u@L$p`R^UsVPb1xe0PoMuY z?|+`WcuIW%+AOkQt`0yloQ~dKK(T-&G{OS*T)Do0f-XSF6tejBgQapu@PfxT@X1GD zYr=R0GeS})_bc%T5Pb)O*UR*{Wddr#=fyg&z`_mV6^PDCUcl=IpGQytW7Eqb>B#`4 zFR*!#&u_ONF8Y*JkWU|P%Plj_A!B-6^02&{oASIJcj2dm=sia zk8_YW(AXkj0y`{RSsU$4*EJ+Oc>k&g7RYYZCZER`)b)!w-cN)yBD26N zpg`(JJ*xEzE|!X}RQ4h%;R?(OP}5_TSX@D*z({j-k`$ia!DsN7NPSFhrI-l)=SNHq z60HIV_Pz!O_T#fnYgdR~ASHpjOb|iUN5EOa30!fYM}QR)xBK1|fR>uw^8FAP8qVT7 z%#Ohj0R}9(rrxt+86k02^j;2gp@TEn5;4MoZZ{>#uD!Zy19)XSl4O7KhxI1g$pKW0)6i))s?0!VJDv#0(*k2@DN9Cl4Sn(AB!BVSxrHm!GDs z7dLHIn4cUM?vI|}M%B!r{0E{^U{!mcDaI@C_srP9){C;i1oST2r%hl)9!_8V)6g6bMf*p{yNSgwZ?&TP!Z(31_o1uNXngcc#j8k$eplqZ{U@ zr_4~%xyM8!ZEI#PrXt2KQT+hN+Eps(!d)X3u6yDC7-FubkqYC4WXB0!O+{7^5-H;o z1~*$I<& z=VmAcQvtMB|+x?Lqgd*ePY(k@YH!jF#=8W0zd~VNQ80G z#CFrri@-?MN?(b$1`A63;>ZrjUd=2?ZnaxOzX)A`6(d9xgGqn zInwK_2(f)oDG0HxQ#M`pZc-y;s4%a+j9QPgvBQ#+=T+^krZibMlZG^0f9>}1l$4rHOOP97iTS9dBc+liZ`%)qHgy2(M}h| z0JSkpsWu=Yk{bA$0ND*;WWx$;;^aSBD|oe)u!0VH*uJdA2z@mVPe#bu;Zyrqueh=T zT-`ZoTyBMx%z^<1evuT>-b=ywWQ6D)PI?Fb5bTUmKY8YgA7FMVoNw(ZB?t8qbN3+L z@)B4c5*W?V_bh5?Q!R=AMB^kz3DX8%D<-WX*@k?q^XyQnC41?J1#G>jPYh`L1KLp5 z@e~OQT@<7d4BQ|G>II$f?me1vXfS?w{kEuxNjLa02gVVmXRPDGMV1g zOS$-DgipurN$`A&+2mKA6lAd9j&l8 z7I+7|1$*;EV_>bILD~v#ky{51Q%Zu!r=Z=eU!JTG%>y^#vps`kwPK6_m1+hkL@%vl zC)9WP8YnczYk;d-r9wl7Wns+B^*Cr&K^HTwSN@UJNxC1n-!GwADZmeC-oeUnc~X9$ znbg5goh$Wp@AK3<#9)a_P{9zrfa8QIWV1#s>{k)hH=Dm05T6qWzS%KfVh~Onz*5V8`EZ)x0*BRuK zGsO03W-Y(ia?xwD)Rz!(F}z`6{ zLbWhb^RRIfx%rz&FVhmX`C0knc% zS0Qz71I&OGw(c=1d7RL;fUOi|0XTH(h;>88YY`j!IN^Y?ny2CQIxS&=8JNyYNr_AY z2f}&z#7cgINFa$8t57meUZthF0qd5N1zdH5f%vGKe&AJF!UQ)N^EPqj1I+|Ol~Kr; z+n?WVpjQ$f)9J74CW@jP!aLBui5)z9c)MosGA*(KT+}rhO2114TLVQy$yQ0%)9&HD zP)odp+ZO`IJdiJdNn!ii;L`C*E%6fSM6tYtp(ct<#j%3z8fk+~eH2y*eytoOp(X2! zU+Zan5V(}~7TPPe2&%}~hxQ7P+5jd0psi&t$46EHo%41m`Bbp7-%!2=dSUcd%`JKV?|VRtDj=B~ykPd12%0A!OXlFJQ3 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 * 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%0Dre1pN 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 delta 53657 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 E0P>%J_5c6? diff --git a/lilypond/string_quartet_3/main/edited/seeds_and_ledgers_3.ly b/lilypond/string_quartet_3/main/edited/seeds_and_ledgers_3.ly index 392d692..66adcf3 100644 --- a/lilypond/string_quartet_3/main/edited/seeds_and_ledgers_3.ly +++ b/lilypond/string_quartet_3/main/edited/seeds_and_ledgers_3.ly @@ -30,8 +30,8 @@ print-first-page-number = ##t print-page-number = ##t - oddHeaderMarkup = \markup { \fill-line { \line { \unless \on-first-page {\pad-markup #2 { \concat {\italic {"test"}}}}}}} - evenHeaderMarkup = \markup { \fill-line { \line { \unless \on-first-page {\pad-markup #2 { \concat {\italic {"test"}}}}}}} + oddHeaderMarkup = \markup { \fill-line { \line { \unless \on-first-page {\pad-markup #2 { \concat {\italic {"seeds and ledges 3"}}}}}}} + evenHeaderMarkup = \markup { \fill-line { \line { \unless \on-first-page {\pad-markup #2 { \concat {\italic {"seeds and ledges 3"}}}}}}} oddFooterMarkup = \markup { \fill-line { \concat { "-" diff --git a/lilypond/string_quartet_3/main/edited/seeds_and_ledgers_3.pdf b/lilypond/string_quartet_3/main/edited/seeds_and_ledgers_3.pdf index 93261feee9b668de8c6856c0239be97d5137bdab..4880f06436b40e07b3dd0f6c490f8de3fd449e96 100644 GIT binary patch delta 61598 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

4PDNWnK_@)BOIVQuiZzC#du8a!`s)Zsy9kr9 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 Szp4Z+)9II8*5$gc>Hi0LYyoZn delta 61092 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 a>X^w>FPuDnLLJLt1?zhC8gkqbb^iwyw(5NV diff --git a/resources/piece_ledger/314s49e1/lilypond/part_I.ly b/resources/piece_ledger/314s49e1/lilypond/part_I.ly index 5fe9b6e..51eaa47 100644 --- a/resources/piece_ledger/314s49e1/lilypond/part_I.ly +++ b/resources/piece_ledger/314s49e1/lilypond/part_I.ly @@ -1,54 +1,56 @@ { - { r4 r8.[ c'16^\markup { \pad-markup #0.2 "+0"}] ~ c'2 ~ } + { r4 r8.[ d'16^\markup { \pad-markup #0.2 "+0"}] ~ d'2 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 } + { d'1 } \bar "|" - { b1^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }} ~ } + { cis'1^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }} ~ } \bar "|" - { b1 ~ } + { cis'1 ~ } \bar "|" - { b4 ~ b8[ ais8^\markup { \pad-markup #0.2 "+35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ ais8.[ a16^\markup { \pad-markup #0.2 "-20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}] ~ a4 ~ } + { cis'4 ~ cis'8[ c'8^\markup { \pad-markup #0.2 "+35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ c'8.[ b16^\markup { \pad-markup #0.2 "-20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}] ~ b4 ~ } \bar "|" - { a1 ~ } + { b1 ~ } \bar "|" - { a1 ~ } + { b1 ~ } + \bar "|" + { b1 ~ } \bar "|" - { a1 ~ } + { b16[ b8.^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }}] ~ b2. } \bar "|" - { a16[ a8.^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }}] ~ a2. } + { ais1^\markup { \pad-markup #0.2 "-13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }} ~ } \bar "|" - { gis1^\markup { \pad-markup #0.2 "-13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }} ~ } + { ais8.[ ais16^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }}] ~ ais2. ~ } \bar "|" - { gis8.[ gis16^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }}] ~ gis2. ~ } + { ais4 ~ ais8[ g8^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ g4 gis4^\markup { \pad-markup #0.2 "-5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↓" }} ~ } \bar "|" - { gis4 ~ gis8[ f8^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ f4 fis4^\markup { \pad-markup #0.2 "-5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↓" }} ~ } + { gis2. ~ gis8[ ais8^\markup { \pad-markup #0.2 "-13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }}] ~ } \bar "|" - { fis2. ~ fis8[ gis8^\markup { \pad-markup #0.2 "-13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }}] ~ } + { ais1 ~ } \bar "|" - { gis1 ~ } + { ais1 ~ } \bar "|" - { gis1 ~ } + { ais1 } \bar "|" - { gis1} + { r1 } \bar "||" } \ No newline at end of file diff --git a/resources/piece_ledger/314s49e1/lilypond/part_II.ly b/resources/piece_ledger/314s49e1/lilypond/part_II.ly index ac6a85b..710340c 100644 --- a/resources/piece_ledger/314s49e1/lilypond/part_II.ly +++ b/resources/piece_ledger/314s49e1/lilypond/part_II.ly @@ -13,27 +13,29 @@ \bar "|" { r1 } \bar "|" - { r16[ ais8.^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }}] ~ ais2. ~ } + { r16[ c'8.^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }}] ~ c'2. ~ } \bar "|" - { ais2. gis4^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }} ~ } + { c'2. ais4^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }} ~ } \bar "|" - { gis16[ fis8.^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }}] ~ fis2. ~ } + { ais16[ gis8.^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }}] ~ gis2. ~ } \bar "|" - { fis1 ~ } + { gis1 ~ } \bar "|" - { fis1 ~ } + { gis1 ~ } \bar "|" - { fis1 ~ } + { gis1 ~ } \bar "|" - { fis1 ~ } + { gis1 ~ } \bar "|" - { fis1 ~ } + { gis1 ~ } \bar "|" - { fis1 ~ } + { gis1 ~ } \bar "|" - { fis1 ~ } + { gis1 ~ } \bar "|" - { fis2 ~ fis8.[ r16] r4 } + { gis2 ~ gis8.[ r16] r4 } + \bar "|" + { r1 } \bar "|" { r1 } \bar "|" diff --git a/resources/piece_ledger/314s49e1/lilypond/part_III.ly b/resources/piece_ledger/314s49e1/lilypond/part_III.ly index 8288ca0..8d307ee 100644 --- a/resources/piece_ledger/314s49e1/lilypond/part_III.ly +++ b/resources/piece_ledger/314s49e1/lilypond/part_III.ly @@ -1,15 +1,15 @@ { - { r2. e'4^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }} ~ } + { r2. fis'4^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }} ~ } \bar "|" - { e'2 e'4^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ e'8.[ f'16^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ } + { fis'2 fis'4^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ fis'8.[ g'16^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ } \bar "|" - { f'4 ~ f'8[ g'8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ g'4 ~ g'8[ ais'8^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ } + { g'4 ~ g'8[ a'8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ a'4 ~ a'8[ c''8^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ } \bar "|" - { ais'4 ~ ais'8[ c''8^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ c''2 } + { c''4 ~ c''8[ d''8^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ d''2 } \bar "|" - { gis'4^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }} ~ gis'8.[ gis'16^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}] ~ gis'4 ~ gis'8[ f'8^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ } + { ais'4^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }} ~ ais'8.[ ais'16^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}] ~ ais'4 ~ ais'8[ g'8^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ } \bar "|" - { f'2 e'4^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ e'8[ r8] } + { g'2 fis'4^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ fis'8[ r8] } \bar "|" { r1 } \bar "|" @@ -21,33 +21,35 @@ \bar "|" { r1 } \bar "|" - { r2 r16[ dis'8.^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }}] ~ dis'4 ~ } + { r2 r16[ f'8.^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }}] ~ f'4 ~ } \bar "|" - { dis'1 ~ } + { f'1 ~ } \bar "|" - { dis'8[ dis'8^\markup { \pad-markup #0.2 "-11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }}] ~ dis'2 d'4^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }} ~ } + { f'8[ f'8^\markup { \pad-markup #0.2 "-11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }}] ~ f'2 e'4^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }} ~ } \bar "|" - { d'1 ~ } + { e'1 ~ } \bar "|" - { d'4 ~ d'8[ ais8^\markup { \pad-markup #0.2 "+35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ ais2 ~ } + { e'4 ~ e'8[ c'8^\markup { \pad-markup #0.2 "+35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ c'2 ~ } \bar "|" - { ais1 ~ } + { c'1 ~ } \bar "|" - { ais8.[ b16^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }}] ~ b2. ~ } + { c'8.[ cis'16^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }}] ~ cis'2. ~ } \bar "|" - { b1 ~ } + { cis'1 ~ } \bar "|" - { b1 ~ } + { cis'1 ~ } \bar "|" - { b1 ~ } + { cis'1 ~ } \bar "|" - { b1 ~ } + { cis'1 ~ } \bar "|" - { b1 ~ } + { cis'1 ~ } \bar "|" - { b1 ~ } + { cis'1 ~ } \bar "|" - { b2 ~ b16[ r8.] r4 } + { cis'2 ~ cis'16[ r8.] r4 } + \bar "|" + { r1 } \bar "|" { r1 } \bar "||" diff --git a/resources/piece_ledger/314s49e1/lilypond/part_IV.ly b/resources/piece_ledger/314s49e1/lilypond/part_IV.ly index 43e8385..dc3e114 100644 --- a/resources/piece_ledger/314s49e1/lilypond/part_IV.ly +++ b/resources/piece_ledger/314s49e1/lilypond/part_IV.ly @@ -1,54 +1,56 @@ { - { c'1^\markup { \pad-markup #0.2 "+0"} ~ } + { d'1^\markup { \pad-markup #0.2 "+0"} ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'4 ~ c'16[ e'8.^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↓" }}] ~ e'2 ~ } + { d'4 ~ d'16[ fis'8.^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↓" }}] ~ fis'2 ~ } \bar "|" - { e'2 ~ e'8.[ g'16^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}] ~ g'4 ~ } + { fis'2 ~ fis'8.[ a'16^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}] ~ a'4 ~ } \bar "|" - { g'4 ~ g'8[ ais'8^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ ais'2 ~ } + { a'4 ~ a'8[ c''8^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ c''2 ~ } \bar "|" - { ais'4 ~ ais'8.[ gis'16^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }}] ~ gis'2 } + { c''4 ~ c''8.[ ais'16^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }}] ~ ais'2 } \bar "|" - { gis'2^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }} ~ gis'8[ g'8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}] ~ g'4 ~ } + { ais'2^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }} ~ ais'8[ a'8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}] ~ a'4 ~ } \bar "|" - { g'8[ f'8^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }}] ~ f'2. ~ } + { a'8[ g'8^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }}] ~ g'2. ~ } \bar "|" - { f'4 ~ f'8[ e'8^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}] ~ e'2 ~ } + { g'4 ~ g'8[ fis'8^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}] ~ fis'2 ~ } \bar "|" - { e'1 ~ } + { fis'1 ~ } \bar "|" - { e'16[ fis'8.^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ fis'2. ~ } + { fis'16[ gis'8.^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ gis'2. ~ } \bar "|" - { fis'1 ~ } + { gis'1 ~ } \bar "|" - { fis'16[ a'8.^\markup { \pad-markup #0.2 "-20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ a'2 ~ a'16[ ais'8.^\markup { \pad-markup #0.2 "+8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↓" }}] ~ } + { gis'16[ b'8.^\markup { \pad-markup #0.2 "-20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ b'2 ~ b'16[ c''8.^\markup { \pad-markup #0.2 "+8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↓" }}] ~ } \bar "|" - { ais'1 ~ } + { c''1 ~ } \bar "|" - { ais'2 ~ ais'16[ b'8.^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ b'4 ~ } + { c''2 ~ c''16[ cis''8.^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ cis''4 ~ } \bar "|" - { b'2 ~ b'8[ a'8^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }}] ~ a'4 ~ } + { cis''2 ~ cis''8[ b'8^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }}] ~ b'4 ~ } \bar "|" - { a'2 ~ a'8.[ fis'16^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }}] ~ fis'4 ~ } + { b'2 ~ b'8.[ gis'16^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }}] ~ gis'4 ~ } \bar "|" - { fis'16[ f'8.^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↑" }}] ~ f'2. ~ } + { gis'16[ g'8.^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↑" }}] ~ g'2. ~ } \bar "|" - { f'4 ~ f'8.[ e'16^\markup { \pad-markup #0.2 "+45"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }}] ~ e'2 ~ } + { g'4 ~ g'8.[ fis'16^\markup { \pad-markup #0.2 "+45"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }}] ~ fis'2 ~ } \bar "|" - { e'1 ~ } + { fis'1 ~ } + \bar "|" + { fis'1 ~ } \bar "|" - { e'1 ~ } + { fis'4 ~ fis'16[ r8.] r2 } \bar "|" - { e'4 ~ e'16[ r8.] r2 } + { r1 } \bar "||" } \ No newline at end of file diff --git a/resources/piece_ledger/4c01589b/lilypond/part_I.ly b/resources/piece_ledger/4c01589b/lilypond/part_I.ly index a806b97..b63de1f 100644 --- a/resources/piece_ledger/4c01589b/lilypond/part_I.ly +++ b/resources/piece_ledger/4c01589b/lilypond/part_I.ly @@ -1,38 +1,40 @@ { - { r2. r8[ e'8^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }}] ~ } + { r2. r8[ fis'8^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }}] ~ } \bar "|" - { e'1 ~ } + { fis'1 ~ } \bar "|" - { e'4 ~ e'8[ f'8^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }}] ~ f'4 ~ f'16[ e'8.^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↓" }}] ~ } + { fis'4 ~ fis'8[ g'8^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }}] ~ g'4 ~ g'16[ fis'8.^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↓" }}] ~ } \bar "|" - { e'1 ~ } + { fis'1 ~ } \bar "|" - { e'2 d'2^\markup { \pad-markup #0.2 "+31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }} ~ } + { fis'2 e'2^\markup { \pad-markup #0.2 "+31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }} ~ } \bar "|" - { d'1 ~ } + { e'1 ~ } \bar "|" - { d'1 ~ } + { e'1 ~ } \bar "|" - { d'1 ~ } + { e'1 ~ } + \bar "|" + { e'1 ~ } \bar "|" - { d'1 ~ } + { e'1 ~ } \bar "|" - { d'1 ~ } + { e'1 ~ } \bar "|" - { d'1 ~ } + { e'2 r2 } \bar "|" - { d'2 r2 } + { r8.[ e'16^\markup { \pad-markup #0.2 "+31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }}] ~ e'2. ~ } \bar "|" - { r8.[ d'16^\markup { \pad-markup #0.2 "+31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }}] ~ d'2. ~ } + { e'1 ~ } \bar "|" - { d'1 ~ } + { e'1 ~ } \bar "|" - { d'1 ~ } + { e'1 ~ } \bar "|" - { d'1 ~ } + { e'1 ~ } \bar "|" - { d'1 ~ } + { e'1 ~ } \bar "|" - { d'1} + { e'16[ r8.] r2. } \bar "||" } \ No newline at end of file diff --git a/resources/piece_ledger/4c01589b/lilypond/part_II.ly b/resources/piece_ledger/4c01589b/lilypond/part_II.ly index 26c0d70..452075b 100644 --- a/resources/piece_ledger/4c01589b/lilypond/part_II.ly +++ b/resources/piece_ledger/4c01589b/lilypond/part_II.ly @@ -1,38 +1,40 @@ { - { c'1^\markup { \pad-markup #0.2 "+0"} ~ } + { d'1^\markup { \pad-markup #0.2 "+0"} ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'2. ~ c'8.[ b16^\markup { \pad-markup #0.2 "-12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ } + { d'2. ~ d'8.[ cis'16^\markup { \pad-markup #0.2 "-12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ } \bar "|" - { b4 b2.^\markup { \pad-markup #0.2 "-39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }} ~ } + { cis'4 cis'2.^\markup { \pad-markup #0.2 "-39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }} ~ } \bar "|" - { b16[ cis'8.^\markup { \pad-markup #0.2 "-47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }}] ~ cis'4 ~ cis'8[ ais8^\markup { \pad-markup #0.2 "+45"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }}] ~ ais4 ~ } + { cis'16[ dis'8.^\markup { \pad-markup #0.2 "-47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }}] ~ dis'4 ~ dis'8[ c'8^\markup { \pad-markup #0.2 "+45"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }}] ~ c'4 ~ } \bar "|" - { ais8[ a8^\markup { \pad-markup #0.2 "+33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}] ~ a8[ b8^\markup { \pad-markup #0.2 "-28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }}] ~ b2 ~ } + { c'8[ b8^\markup { \pad-markup #0.2 "+33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}] ~ b8[ cis'8^\markup { \pad-markup #0.2 "-28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }}] ~ cis'2 ~ } \bar "|" - { b8.[ c'16^\markup { \pad-markup #0.2 "+0"}] ~ c'2 ~ c'8.[ b16^\markup { \pad-markup #0.2 "-39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ } + { cis'8.[ d'16^\markup { \pad-markup #0.2 "+0"}] ~ d'2 ~ d'8.[ cis'16^\markup { \pad-markup #0.2 "-39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ } \bar "|" - { b1 ~ } + { cis'1 ~ } \bar "|" - { b1 ~ } + { cis'1 ~ } \bar "|" - { b2 c'2^\markup { \pad-markup #0.2 "+0"} ~ } + { cis'2 d'2^\markup { \pad-markup #0.2 "+0"} ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'8.[ r16] r2. } + { d'8.[ r16] r2. } + \bar "|" + { r1 } \bar "||" } \ No newline at end of file diff --git a/resources/piece_ledger/4c01589b/lilypond/part_III.ly b/resources/piece_ledger/4c01589b/lilypond/part_III.ly index 69e87d9..e1a0b8e 100644 --- a/resources/piece_ledger/4c01589b/lilypond/part_III.ly +++ b/resources/piece_ledger/4c01589b/lilypond/part_III.ly @@ -1,38 +1,40 @@ { - { r2. r8[ ais8^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}] ~ } + { r2. r8[ c'8^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}] ~ } \bar "|" - { ais2 gis2^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }} ~ } + { c'2 ais2^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }} ~ } \bar "|" - { gis4 ~ gis8[ g8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }}] ~ g2 ~ } + { ais4 ~ ais8[ a8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }}] ~ a2 ~ } \bar "|" - { g1 ~ } + { a1 ~ } \bar "|" - { g1 ~ } + { a1 ~ } \bar "|" - { g1 ~ } + { a1 ~ } \bar "|" - { g1 ~ } + { a1 ~ } \bar "|" - { g1 ~ } + { a1 ~ } \bar "|" - { g1 ~ } + { a1 ~ } \bar "|" - { g8.[ g16^\markup { \pad-markup #0.2 "+29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }}] ~ g8.[ a16^\markup { \pad-markup #0.2 "+33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}] ~ a2 ~ } + { a8.[ a16^\markup { \pad-markup #0.2 "+29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }}] ~ a8.[ b16^\markup { \pad-markup #0.2 "+33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}] ~ b2 ~ } \bar "|" - { a8.[ gis16^\markup { \pad-markup #0.2 "+30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}] ~ gis2 ~ gis8.[ a16^\markup { \pad-markup #0.2 "-20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }}] ~ } + { b8.[ ais16^\markup { \pad-markup #0.2 "+30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}] ~ ais2 ~ ais8.[ b16^\markup { \pad-markup #0.2 "-20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }}] ~ } \bar "|" - { a2 r2 } + { b2 r2 } \bar "|" { r1 } \bar "|" - { r16[ gis8.^\markup { \pad-markup #0.2 "-18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }}] ~ gis2. } + { r16[ ais8.^\markup { \pad-markup #0.2 "-18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }}] ~ ais2. } \bar "|" - { gis4^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }} ~ gis8[ gis8^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }}] ~ gis2 } + { ais4^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }} ~ ais8[ ais8^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }}] ~ ais2 } \bar "|" - { g2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} g2^\markup { \pad-markup #0.2 "+29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }} ~ } + { a2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} a2^\markup { \pad-markup #0.2 "+29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }} ~ } \bar "|" - { g8.[ a16^\markup { \pad-markup #0.2 "-20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }}] ~ a2. ~ } + { a8.[ b16^\markup { \pad-markup #0.2 "-20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }}] ~ b2. ~ } \bar "|" - { a1} + { b1 ~ } + \bar "|" + { b16[ r8.] r2. } \bar "||" } \ No newline at end of file diff --git a/resources/piece_ledger/4c01589b/lilypond/part_IV.ly b/resources/piece_ledger/4c01589b/lilypond/part_IV.ly index 2ab46c8..8df7bd6 100644 --- a/resources/piece_ledger/4c01589b/lilypond/part_IV.ly +++ b/resources/piece_ledger/4c01589b/lilypond/part_IV.ly @@ -1,38 +1,40 @@ { - { r2. r8[ gis8^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }}] ~ } + { r2. r8[ ais8^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }}] ~ } \bar "|" - { gis1 ~ } + { ais1 ~ } \bar "|" - { gis4 ~ gis8[ ais8^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}] ~ ais4 ~ ais16[ d'8.^\markup { \pad-markup #0.2 "+31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }}] ~ } + { ais4 ~ ais8[ c'8^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}] ~ c'4 ~ c'16[ e'8.^\markup { \pad-markup #0.2 "+31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }}] ~ } \bar "|" - { d'2 ~ d'8[ f'8^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }}] ~ f'4 ~ } + { e'2 ~ e'8[ g'8^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }}] ~ g'4 ~ } \bar "|" - { f'2 g'2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } + { g'2 a'2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } \bar "|" - { g'1 ~ } + { a'1 ~ } \bar "|" - { g'1 ~ } + { a'1 ~ } \bar "|" - { g'1 ~ } + { a'1 ~ } \bar "|" - { g'1 ~ } + { a'1 ~ } \bar "|" - { g'1 ~ } + { a'1 ~ } \bar "|" - { g'1 ~ } + { a'1 ~ } \bar "|" - { g'1 ~ } + { a'1 ~ } \bar "|" - { g'1 ~ } + { a'1 ~ } \bar "|" - { g'1 ~ } + { a'1 ~ } \bar "|" - { g'1 ~ } + { a'1 ~ } \bar "|" - { g'1 ~ } + { a'1 ~ } \bar "|" - { g'1 ~ } + { a'1 ~ } \bar "|" - { g'8.[ r16] r2. } + { a'8.[ r16] r2. } + \bar "|" + { r1 } \bar "||" } \ No newline at end of file diff --git a/resources/piece_ledger/7e170ef8/lilypond/part_I.ly b/resources/piece_ledger/7e170ef8/lilypond/part_I.ly index c8ca6a7..b5838f7 100644 --- a/resources/piece_ledger/7e170ef8/lilypond/part_I.ly +++ b/resources/piece_ledger/7e170ef8/lilypond/part_I.ly @@ -1,34 +1,36 @@ { - { r2. r8[ e'8^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }}] ~ } + { r2. r8[ fis'8^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }}] ~ } \bar "|" - { e'8.[ f'16^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }}] ~ f'4 ~ f'8[ e'8^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↓" }}] ~ e'4 ~ } + { fis'8.[ g'16^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }}] ~ g'4 ~ g'8[ fis'8^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↓" }}] ~ fis'4 ~ } \bar "|" - { e'4 ~ e'16[ fis'8.^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↑" }}] ~ fis'16[ g'8.^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }}] ~ g'4 ~ } + { fis'4 ~ fis'16[ gis'8.^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↑" }}] ~ gis'16[ a'8.^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }}] ~ a'4 ~ } \bar "|" - { g'8.[ gis'16^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }}] ~ gis'2. ~ } + { a'8.[ ais'16^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }}] ~ ais'2. ~ } \bar "|" - { gis'2. ~ gis'8.[ fis'16^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }}] ~ } + { ais'2. ~ ais'8.[ gis'16^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }}] ~ } \bar "|" - { fis'2. ~ fis'16[ fis'8.^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }}] ~ } + { gis'2. ~ gis'16[ gis'8.^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }}] ~ } \bar "|" - { fis'2 ~ fis'8.[ gis'16^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ gis'4 ~ } + { gis'2 ~ gis'8.[ ais'16^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ ais'4 ~ } \bar "|" - { gis'1 ~ } + { ais'1 ~ } \bar "|" - { gis'2 gis'2^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } + { ais'2 ais'2^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } \bar "|" - { gis'1 ~ } + { ais'1 ~ } \bar "|" - { gis'1 ~ } + { ais'1 ~ } \bar "|" - { gis'1 ~ } + { ais'1 ~ } \bar "|" - { gis'1 ~ } + { ais'1 ~ } \bar "|" - { gis'2. ~ gis'16[ ais'8.^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ } + { ais'2. ~ ais'16[ c''8.^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ } \bar "|" - { ais'4 ~ ais'8.[ c''16^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ c''2 ~ } + { c''4 ~ c''8.[ d''16^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ d''2 ~ } \bar "|" - { c''16[ cis''8.^\markup { \pad-markup #0.2 "+39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }}] ~ cis''2 ~ cis''16[ d''8.^\markup { \pad-markup #0.2 "+31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}]} + { d''16[ dis''8.^\markup { \pad-markup #0.2 "+39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }}] ~ dis''2 ~ dis''16[ e''8.^\markup { \pad-markup #0.2 "+31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ } + \bar "|" + { e''4 ~ e''8.[ r16] r2 } \bar "||" } \ No newline at end of file diff --git a/resources/piece_ledger/7e170ef8/lilypond/part_II.ly b/resources/piece_ledger/7e170ef8/lilypond/part_II.ly index 7683e88..4288d43 100644 --- a/resources/piece_ledger/7e170ef8/lilypond/part_II.ly +++ b/resources/piece_ledger/7e170ef8/lilypond/part_II.ly @@ -1,23 +1,23 @@ { - { c'1^\markup { \pad-markup #0.2 "+0"} ~ } + { d'1^\markup { \pad-markup #0.2 "+0"} ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'2. ~ c'8.[ d'16^\markup { \pad-markup #0.2 "+31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}] ~ } + { d'2. ~ d'8.[ e'16^\markup { \pad-markup #0.2 "+31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}] ~ } \bar "|" - { d'1 ~ } + { e'1 ~ } \bar "|" - { d'1 ~ } + { e'1 ~ } \bar "|" - { d'1 ~ } + { e'1 ~ } \bar "|" - { d'1 ~ } + { e'1 ~ } \bar "|" - { d'8.[ r16] r2. } + { e'8.[ r16] r2. } \bar "|" { r1 } \bar "|" @@ -25,10 +25,12 @@ \bar "|" { r1 } \bar "|" - { r2. r16[ d'8.^\markup { \pad-markup #0.2 "+31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}] ~ } + { r2. r16[ e'8.^\markup { \pad-markup #0.2 "+31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}] ~ } \bar "|" - { d'1 ~ } + { e'1 ~ } + \bar "|" + { e'1 ~ } \bar "|" - { d'1} + { e'4 ~ e'8.[ r16] r2 } \bar "||" } \ No newline at end of file diff --git a/resources/piece_ledger/7e170ef8/lilypond/part_III.ly b/resources/piece_ledger/7e170ef8/lilypond/part_III.ly index c3f7109..e72209f 100644 --- a/resources/piece_ledger/7e170ef8/lilypond/part_III.ly +++ b/resources/piece_ledger/7e170ef8/lilypond/part_III.ly @@ -1,34 +1,36 @@ { - { r2. r8[ ais8^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}] ~ } + { r2. r8[ c'8^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}] ~ } \bar "|" - { ais1 ~ } + { c'1 ~ } \bar "|" - { ais4 ~ ais16[ g8.^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }}] ~ g16[ gis8.^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }}] ~ gis4 ~ } + { c'4 ~ c'16[ a8.^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }}] ~ a16[ ais8.^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }}] ~ ais4 ~ } \bar "|" - { gis8.[ gis16^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ gis2. ~ } + { ais8.[ ais16^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ ais2. ~ } \bar "|" - { gis2. ~ gis8.[ ais16^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ } + { ais2. ~ ais8.[ c'16^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ } \bar "|" - { ais1 ~ } + { c'1 ~ } \bar "|" - { ais2 ~ ais8.[ gis16^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }}] ~ gis4 ~ } + { c'2 ~ c'8.[ ais16^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }}] ~ ais4 ~ } \bar "|" - { gis2 ~ gis16[ gis8.^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}] ~ gis4 ~ } + { ais2 ~ ais16[ ais8.^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}] ~ ais4 ~ } + \bar "|" + { ais1 ~ } \bar "|" - { gis1 ~ } + { ais2. ~ ais8[ a8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ } \bar "|" - { gis2. ~ gis8[ g8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ } + { a4 ~ a8[ c'8^\markup { \pad-markup #0.2 "+45"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↓" }}] ~ c'4 ~ c'8.[ e'16^\markup { \pad-markup #0.2 "-35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }}] ~ } \bar "|" - { g4 ~ g8[ ais8^\markup { \pad-markup #0.2 "+45"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↓" }}] ~ ais4 ~ ais8.[ d'16^\markup { \pad-markup #0.2 "-35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }}] ~ } + { e'2. dis'4^\markup { \pad-markup #0.2 "+12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }} ~ } \bar "|" - { d'2. cis'4^\markup { \pad-markup #0.2 "+12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }} ~ } + { dis'2 ~ dis'8[ fis'8^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ fis'4 ~ } \bar "|" - { cis'2 ~ cis'8[ e'8^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ e'4 ~ } + { fis'8.[ g'16^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ g'2. ~ } \bar "|" - { e'8.[ f'16^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ f'2. ~ } + { g'1 ~ } \bar "|" - { f'1 ~ } + { g'1 ~ } \bar "|" - { f'1} + { g'4 ~ g'8.[ r16] r2 } \bar "||" } \ No newline at end of file diff --git a/resources/piece_ledger/7e170ef8/lilypond/part_IV.ly b/resources/piece_ledger/7e170ef8/lilypond/part_IV.ly index 1bf0348..4e63ca1 100644 --- a/resources/piece_ledger/7e170ef8/lilypond/part_IV.ly +++ b/resources/piece_ledger/7e170ef8/lilypond/part_IV.ly @@ -7,28 +7,30 @@ \bar "|" { r1 } \bar "|" - { r8[ c'8^\markup { \pad-markup #0.2 "+0"}] ~ c'2. ~ } + { r8[ d'8^\markup { \pad-markup #0.2 "+0"}] ~ d'2. ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1 ~ } + { d'1 ~ } \bar "|" - { c'1} + { d'1 ~ } + \bar "|" + { d'4 ~ d'8.[ r16] r2 } \bar "||" } \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas.json b/resources/resources_bak_2024_01_03/piece_ledger_pas.json deleted file mode 100644 index f04a134..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas.json +++ /dev/null @@ -1,27 +0,0 @@ -{ -"ledger": -[ - "314s49e1", - "7e170ef8", - "7ac10d34", - "628d5c8b", - "6abf27d4", - "6d743c5c", - "5625a95a", - "5267b235", - "6a3f7c7c", - "6d0c2f19", - "7bf874ce", - "50fec831", - "7fd4d544", - "6f1305ed", - "7c7a96a2", - "7c8bc6df", - "46210507", - "74faf83f", - "703e109b", - "4b96f62d", - "449aeaa6", - "6409252e" -] -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas.json_bak b/resources/resources_bak_2024_01_03/piece_ledger_pas.json_bak deleted file mode 100644 index f69bd2d..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas.json_bak +++ /dev/null @@ -1,26 +0,0 @@ -{ -"ledger": -[ - "314s49e1", - "7e170ef8", - "7ac10d34", - "628d5c8b", - "6abf27d4", - "6d743c5c", - "5625a95a", - "5267b235", - "6a3f7c7c", - "6d0c2f19", - "7bf874ce", - "50fec831", - "7fd4d544", - "6f1305ed", - "7c7a96a2", - "7c8bc6df", - "46210507", - "74faf83f", - "703e109b", - "4b96f62d", - "449aeaa6" -] -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/314s49e1/314s49e1_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/314s49e1/314s49e1_code.scd deleted file mode 100644 index 2d77a32..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/314s49e1/314s49e1_code.scd +++ /dev/null @@ -1,581 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrder, genSubMotif, updateVoices; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var writeResources, prettifyArray, setSeeds, sanityCheck, msgInterpret; - -// global vars (many set by OSC funcs at bottom) -var refSeed, seed, lastXChanges, popSize, exPath, dir, primes, dims, tuples, ranges, durFunc, seq, group, player; - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genOrder = {arg minLength = 0, maxLength = 5; - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noProgIns = (popSize - 1).rand + 1; - noSusIns = (popSize - noProgIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxLength - minLength).rand + minLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = [1, 1, 1, 1, 1]; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, res, lastIns, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - lastIns = nil; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - (silent ++ sus ++ prog).do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - //dur = [durFunc.value(), 0].wchoose([1, 0].normalizeSum); - dur = durFunc.value(lastIns, ins); - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur.round(0.125)]); - }); - - lastIns = ins; - }); - - // pad ending - if(isLastOrder, { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - //dur = [durFunc.value(), 0].wchoose([1, 0].normalizeSum); - dur = durFunc.value(lastIns, ins); - res = res.add([voices.deepCopy.postln, dur.round(0.125)]); - }); - lastIns = ins; - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold}); - res; -}; - - -//------primary routines - -genMotif = {arg inOrders; - var orders, repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - orders = inOrders; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -genPatterns = {arg seq; - var voices, durs, patterns, res; - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice; - var clumps, hdScores, freqs, fDurs; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \instrument, \test, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1) - ); - }); - ); - res -}; - -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; - - -//------resource management funcs - -setSeeds = {arg inRefSeed, inSeed; - refSeed = if(inRefSeed.isNumber, {inRefSeed.asInteger}, {nil}); - seed = if(inSeed > 1, {inSeed.asInteger}, {rrand(100000, 999999)}); - thisThread.randSeed = seed; -}; - -prettifyArray = {arg data, finDepth = 1; - var prettyString = "", rCount = 0, writeArray; - - writeArray = {arg array; - var depth, indent; - depth = array.maxDepth; - indent = rCount.collect({" "}).join(""); - prettyString = prettyString ++ indent ++ "[\n"; - rCount = rCount + 1; - if(depth > 5, { - array.do({arg subArray; - writeArray.value(subArray); - }); - }, { - array.do({arg data, d; - prettyString = prettyString ++ indent ++ " " ++ data.asCompileString ++ if(d != (array.size - 1), {",\n"}, {""}); - }); - }); - rCount = rCount - 1; - if(rCount < (finDepth - 1), {prettyString = prettyString.drop((finDepth - 1).neg)}); - //if(rCount == 0, {prettyString = prettyString.drop((finDepth - 1).neg)}); - prettyString = prettyString ++ "\n" ++ indent ++ "]" ++ if(rCount > 0, {",\n"}, {""}); - }; - - writeArray.value(data); - prettyString -}; - -writeResources = {arg seq, path; - var dir, file, resString; - file = File(path,"w"); - - resString = "{\nmusic_data:\n"; - resString = resString ++ prettifyArray.value(seq, 3); - - resString = resString ++ ",\nlast_changes:\n"; - resString = resString ++ prettifyArray.value(lastXChanges, 1); - - resString = resString ++ ",\nseed: " ++ seed ++ ",\nref_seed: " ++ refSeed ++ "\n}"; - - file.write(resString); - file.close; -}; - -sanityCheck = {arg motif, index; - //print functions - very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in; - var res; - res = in.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - res = res.replace("\'", "").replace("\"", "").replace("Rest", "\"Rest\""); - res.interpret -}; - - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -refSeed = nil; -group = Group.new; - - -//------OSC funcs - -OSCdef(\gen, {arg msg, time, addr, port; - var orders, condition; - msg.postln; - durFunc = nil; - - addr.sendMsg("/STATE/SEND"); - - { - while({durFunc == nil}, {0.1.wait}); - setSeeds.value(msg[1].postln, msg[2]); - - lastXChanges = if(refSeed == nil, { - [initVoices.value().deepCopy]; - }, { - var file; - file = File((dir +/+ "resources" +/+ refSeed ++ "_music" ++ ".json").standardizePath, "r"); - msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - if(msg.size == 4, { - orders = msgInterpret.value(msg[3]); - }, { - var minLength, maxLength; - minLength = msg[3]; - maxLength = msg[4]; - orders = ((maxLength - minLength).rand + minLength).collect({genOrder.value(msg[5], msg[6])}); - }); - - orders.postln; - seed.postln; - refSeed.postln; - - seq = genMotif.value(orders); - //patterns = genPatterns.value(seq); - addr.sendMsg("/current_seed", seed); - addr.sendMsg("/order", prettifyArray.value(orders, 1)); - addr.sendMsg("/mus_seq", prettifyArray.value(seq, 3)); - }.fork; - -}, \gen); - -OSCdef(\commit, {arg msg, time, addr, port; - var ledgerPath, oldLedger, newLedger, musSeq; - //msg.postln; - seed.postln; - //File.copy(exPath, (dir +/+ "resources" +/+ seed ++ "_code" ++ ".scd").standardizePath); - //addr.sendMsg("/SESSION/SAVE", (dir +/+ "resources" +/+ seed ++ "_gui_session" ++ ".json").standardizePath); - //addr.sendMsg("/STATE/SAVE", (dir +/+ "resources" +/+ seed ++ "_gui_state" ++ ".state").standardizePath); - - writeResources.value(seq, (dir +/+ "resources" +/+ seed ++ "_music" ++ ".json").standardizePath); - - ledgerPath = (dir +/+ "resources" +/+ "piece_ledger" ++ ".json").standardizePath; - oldLedger = File(ledgerPath, "r"); - musSeq = msgInterpret.value(oldLedger.readAllString.parseJSON["ledger"]); - oldLedger.close; - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - newLedger = File(ledgerPath, "w"); - musSeq = musSeq.add(seed); - newLedger.write("{\nledger:\n" ++ prettifyArray.value(musSeq, 1) ++ "\n}"); - newLedger.close; - - //refSeed = seed; -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - player.stop; - group.set(\gate, 0); - }, { - var cSize, ledgerPath, ledger, patterns, pSeq; - ledgerPath = (dir +/+ "resources" +/+ "piece_ledger" ++ ".json").standardizePath; - ledger = msgInterpret.value(File(ledgerPath, "r").readAllString.parseJSON["ledger"]); - pSeq = []; - if(msg[2].asString != "all", {ledger = ledger.keep(msg[2].asInteger - 1)}); - ledger.do({arg rSeed; - var file; - file = File((dir +/+ "resources" +/+ rSeed.postln ++ "_music" ++ ".json").standardizePath, "r"); - pSeq = pSeq.add(msgInterpret.value(file.readAllString.parseJSON["music_data"])); - file.close; - }); - pSeq = pSeq.add(seq); - patterns = genPatterns.value(pSeq); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - }); - player = player.play - }); -}, \transport); - -OSCdef(\range, {arg msg; - msg.postln; - ranges[msg[1]][msg[2]] = msg[3] -}, \range); - -OSCdef(\dur_probs_env, {arg msg; - var env, pTable, min, max, cProb; - msg.postln; - env = Env.pairs([[0, 0]] ++ msg[4..].clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - min = msg[1]; - max = msg[2]; - cProb = msg[3]; - durFunc = {arg lIns, cIns; - if(lIns.postln == cIns.postln, { - pTable.tableRand * (max - min) + min - }, { - if(1.0.rand < cProb.postln, {0}, {pTable.tableRand * (max - min) + min}).postln; - }); - }; -}, \dur_probs_env); -) - -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms; - noHarms = 30; - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) - -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) - - -File((~dir +/+ "resources" +/+ 517313 ++ "_music" ++ ".json").standardizePath, "r").readAllString.parseJSON["last_changes"].asString.interpret[0][0][0].isNumber - -"{\"a\": 1}".parseYAML["a"].asInteger; -"{\"a\": 1}".parseJSON["a"].isNumber; \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/314s49e1/314s49e1_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/314s49e1/314s49e1_mus_model.json deleted file mode 100644 index c78a753..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/314s49e1/314s49e1_mus_model.json +++ /dev/null @@ -1,74 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 0.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 1.5 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 1.0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 1.0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 1.25 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 1 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 1.25 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 0.75 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 0.875 ], - [ [ [ 1, 0, 0, 0, 0, -1 ], [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 1.5 ], - [ [ [ 1, 0, 0, 0, 0, -1 ], [ "Rest" ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.25 ], - [ [ [ 0, 1, 0, 0, 0, 0 ], [ "Rest" ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.375 ], - [ [ [ 0, 0, 0, 1, 0, 0 ], [ "Rest" ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0.75 ], - [ [ [ 0, 0, 0, 1, 0, 0 ], [ "Rest" ], [ 0, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0.625 ], - [ [ [ 0, 0, 0, 1, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0.75 ], - [ [ [ 0, 0, 0, 0, 0, 1 ], [ "Rest" ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.125 ], - [ [ [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.25 ], - [ [ [ 0, 1, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.0 ], - [ [ [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0.875 ] - ], - [ - [ [ [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, -1, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0.875 ], - [ [ [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, -1, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 0.75 ], - [ [ [ 0, 0, 0, 1, -1, 0 ], [ 1, 0, -1, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 1.5 ], - [ [ [ 0, 0, 0, 1, -1, 0 ], [ 0, 0, 0, 0, -1, 1 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 1.25 ], - [ [ [ 0, 0, 0, 1, -1, 0 ], [ 0, 1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 0.625 ], - [ [ [ 1, 0, 0, 0, -1, 0 ], [ 0, 1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 0.625 ], - [ [ [ 1, 0, 0, 0, -1, 0 ], [ 0, 1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 1, 0, -1, 0 ] ], 0.625 ], - [ [ [ 1, 0, 0, 0, -1, 0 ], [ 0, 1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, 0, 0, -1, -1, 0 ] ], 1.375 ], - [ [ [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 1, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, 0, 0, -1, -1, 0 ] ], 1.375 ], - [ [ [ 2, 0, 0, -1, -1, 0 ], [ 0, 0, 1, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, 0, 0, -1, -1, 0 ] ], 1.5 ], - [ [ [ 2, 0, 0, 0, -1, -1 ], [ 0, 0, 1, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, 0, 0, -1, -1, 0 ] ], 0.75 ], - [ [ [ 2, 0, 0, 0, -1, -1 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, 0, 0, -1, -1, 0 ] ], 1.0 ] - ], - [ - [ [ [ 2, 0, 0, 0, -1, -1 ], [ 1, -1, 0, 0, -1, 0 ], [ "Rest" ], [ 1, 0, 0, -1, -1, 0 ] ], 0.75 ], - [ [ [ 2, 0, 0, 0, -1, -1 ], [ 1, -1, 0, 0, -1, 0 ], [ "Rest" ], [ 0, -1, 0, 1, -1, 0 ] ], 1.0 ], - [ [ [ 2, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ "Rest" ], [ 0, -1, 0, 1, -1, 0 ] ], 0.875 ], - [ [ [ 2, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ "Rest" ], [ 0, -1, 0, 0, -1, 1 ] ], 1.25 ], - [ [ [ 1, -1, 0, 1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ "Rest" ], [ 0, -1, 0, 0, -1, 1 ] ], 1.125 ], - [ [ [ 1, -1, 0, 1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ "Rest" ], [ 1, -1, -1, 0, -1, 0 ] ], 1.0 ], - [ [ [ 1, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ "Rest" ], [ 1, -1, -1, 0, -1, 0 ] ], 0.75 ], - [ [ [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ "Rest" ], [ 1, -1, -1, 0, -1, 0 ] ], 0.625 ], - [ [ [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ "Rest" ], [ 0, -1, 0, 0, 0, 0 ] ], 0.75 ], - [ [ [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ "Rest" ], [ 1, -1, 0, 0, -2, 0 ] ], 1.375 ], - [ [ [ 2, -2, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ "Rest" ], [ 1, -1, 0, 0, -2, 0 ] ], 0.875 ], - [ [ [ 2, -2, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ "Rest" ], [ 0, -1, 0, 0, -1, 1 ] ], 3.375 ], - [ [ [ 2, -2, 0, 0, -1, 0 ], [ "Rest" ], [ "Rest" ], [ 0, -1, 0, 0, -1, 1 ] ], 1.5 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 0, -1, 0, 0, -1, 1 ] ], 1.375 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.0 ] - ] - ] -], -"last_changes": -[ - [ [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, -1, 0, -1, 0 ] ], - [ [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, -1, 0, 0, 0, 0 ] ], - [ [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -2, 0 ] ], - [ [ 2, -2, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -2, 0 ] ], - [ [ 2, -2, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, -1, 0, 0, -1, 1 ] ] -], -"ref_uid": "nil" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/449aeaa6/449aeaa6_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/449aeaa6/449aeaa6_code.scd deleted file mode 100644 index 3ec9b1a..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/449aeaa6/449aeaa6_code.scd +++ /dev/null @@ -1,907 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1, 3)}, {rrand(0.3, 0.5)}); - }); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - ledger = ledger.drop(-1).add(curUID); - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, attack, release = 1, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = rrand(20, 40); - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - //sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * amp * EnvGen.kr(Env.adsr(attack, 0.3, 0.9, release, 0.9, -3), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); - //Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.sine(dur), gate, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs, hierarchicalDust; - - hierarchicalDust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) - ); - - sigs = [~stringModelBusArray, ~sineBusArray, ~bassBusArray, ~hdustBusArray, ~samplerBusArray].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -mixer = Synth.tail(~group, \mixer); -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/449aeaa6/449aeaa6_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/449aeaa6/449aeaa6_mus_model.json deleted file mode 100644 index dde9e73..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/449aeaa6/449aeaa6_mus_model.json +++ /dev/null @@ -1,83 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, 0, 0, 0, -1 ], [ "Rest" ] ], 4 ], - [ [ [ "Rest" ], [ 0, 1, 0, 1, 0, -1 ], [ 0, 1, 0, 0, 0, -1 ], [ "Rest" ] ], 2 ], - [ [ [ "Rest" ], [ 0, 1, 0, 1, 0, -1 ], [ 0, 1, 0, 0, 0, -1 ], [ 1, 1, 0, 0, -1, -1 ] ], 1.875 ], - [ [ [ -1, 1, 0, 1, 0, -1 ], [ 0, 1, 0, 1, 0, -1 ], [ 0, 1, 0, 0, 0, -1 ], [ 1, 1, 0, 0, -1, -1 ] ], 1.625 ], - [ [ [ -1, 1, 0, 1, 0, -1 ], [ 0, 1, 0, 1, 0, -1 ], [ 0, 1, 0, 0, 0, -1 ], [ 0, 2, 0, 0, 0, -1 ] ], 1.75 ], - [ [ [ -1, 2, 0, 0, 0, -1 ], [ 0, 1, 0, 1, 0, -1 ], [ 0, 1, 0, 0, 0, -1 ], [ 0, 2, 0, 0, 0, -1 ] ], 1.875 ], - [ [ [ -1, 1, 0, 0, 0, 0 ], [ 0, 1, 0, 1, 0, -1 ], [ 0, 1, 0, 0, 0, -1 ], [ 0, 2, 0, 0, 0, -1 ] ], 0 ], - [ [ [ -1, 1, 0, 0, 0, 0 ], [ 1, 1, 0, 0, 0, -1 ], [ 0, 1, 0, 0, 0, -1 ], [ 0, 2, 0, 0, 0, -1 ] ], 2 ], - [ [ [ -1, 1, 0, 0, 0, 0 ], [ 2, 1, 0, -1, 0, -1 ], [ 0, 1, 0, 0, 0, -1 ], [ 0, 2, 0, 0, 0, -1 ] ], 1.375 ], - [ [ [ 0, 1, -1, 0, 0, -1 ], [ 2, 1, 0, -1, 0, -1 ], [ 0, 1, 0, 0, 0, -1 ], [ 0, 2, 0, 0, 0, -1 ] ], 1 ], - [ [ [ 0, 1, -1, 0, 0, -1 ], [ 2, 1, 0, 0, 0, -2 ], [ 0, 1, 0, 0, 0, -1 ], [ 0, 2, 0, 0, 0, -1 ] ], 7.375 ] - ], - [ - [ [ [ -1, 2, 0, 0, 0, -1 ], [ 2, 1, 0, 0, 0, -2 ], [ 0, 1, 0, 0, 0, -1 ], [ 0, 2, 0, 0, 0, -1 ] ], 0 ], - [ [ [ -1, 2, 0, 0, 0, -1 ], [ 2, 1, 0, 0, 0, -2 ], [ 0, 1, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ -1, 2, 0, 0, 0, -1 ], [ 2, 0, 0, 0, 0, -1 ], [ 0, 1, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, -1 ] ], 5.375 ] - ], - [ - [ [ [ -1, 2, 0, 0, 0, -1 ], [ "Rest" ], [ 0, 1, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ -1, 2, 0, 0, 0, -1 ], [ "Rest" ], [ 0, 1, 0, 0, 0, -1 ], [ "Rest" ] ], 2 ], - [ [ [ -1, 2, 0, 0, 0, -1 ], [ "Rest" ], [ -1, 2, 1, 0, 0, -1 ], [ "Rest" ] ], 1.25 ], - [ [ [ -1, 2, 0, 0, 0, -1 ], [ "Rest" ], [ -1, 2, 0, 0, 1, -1 ], [ "Rest" ] ], 1.875 ], - [ [ [ -1, 2, 0, 0, 0, -1 ], [ "Rest" ], [ 0, 2, 0, 0, -1, -1 ], [ "Rest" ] ], 1.25 ], - [ [ [ -1, 2, 0, 0, 0, -1 ], [ "Rest" ], [ -1, 3, 0, 0, 0, -1 ], [ "Rest" ] ], 1.375 ], - [ [ [ -1, 2, 0, 0, 0, -1 ], [ "Rest" ], [ 0, 2, -1, 0, 0, -1 ], [ "Rest" ] ], 8.375 ] - ], - [ - [ [ [ -1, 2, 0, 0, 0, -1 ], [ 2, 2, -1, 0, 0, -2 ], [ 0, 2, -1, 0, 0, -1 ], [ "Rest" ] ], 1.75 ], - [ [ [ -1, 2, 0, 0, 0, -1 ], [ 2, 2, -1, 0, 0, -2 ], [ 0, 2, -1, 0, 0, -1 ], [ 1, 2, -1, 0, 0, -2 ] ], 0 ], - [ [ [ -1, 2, -1, 0, 1, -1 ], [ 2, 2, -1, 0, 0, -2 ], [ 0, 2, -1, 0, 0, -1 ], [ 1, 2, -1, 0, 0, -2 ] ], 2 ], - [ [ [ 0, 2, -1, 0, 0, -2 ], [ 2, 2, -1, 0, 0, -2 ], [ 0, 2, -1, 0, 0, -1 ], [ 1, 2, -1, 0, 0, -2 ] ], 1.5 ], - [ [ [ 0, 2, -1, 0, 0, -2 ], [ 2, 2, -1, -1, 0, -1 ], [ 0, 2, -1, 0, 0, -1 ], [ 1, 2, -1, 0, 0, -2 ] ], 7 ] - ], - [ - [ [ [ 0, 2, -1, 0, 0, -2 ], [ "Rest" ], [ 0, 2, -1, 0, 0, -1 ], [ 1, 2, -1, 0, 0, -2 ] ], 1.5 ], - [ [ [ 0, 2, -1, 0, 0, -2 ], [ "Rest" ], [ 0, 2, -1, 0, 0, -1 ], [ "Rest" ] ], 1.25 ], - [ [ [ 0, 2, -1, -1, 0, -1 ], [ "Rest" ], [ 0, 2, -1, 0, 0, -1 ], [ "Rest" ] ], 1.875 ], - [ [ [ -1, 2, -1, 0, 0, -1 ], [ "Rest" ], [ 0, 2, -1, 0, 0, -1 ], [ "Rest" ] ], 1.5 ], - [ [ [ -2, 2, -1, 0, 0, 0 ], [ "Rest" ], [ 0, 2, -1, 0, 0, -1 ], [ "Rest" ] ], 1 ], - [ [ [ -1, 2, -2, 0, 0, -1 ], [ "Rest" ], [ 0, 2, -1, 0, 0, -1 ], [ "Rest" ] ], 1.375 ], - [ [ [ -2, 2, -1, 1, 0, -1 ], [ "Rest" ], [ 0, 2, -1, 0, 0, -1 ], [ "Rest" ] ], 6.75 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 2, -1, 0, 0, -1 ], [ "Rest" ] ], 1.125 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 7.5 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 2, -1, -1, 0, -1 ], [ 2, 2, -1, -1, 0, -1 ], [ 0, 2, -1, 0, 0, -1 ], [ 1, 2, -1, 0, 0, -2 ] ], - [ [ -1, 2, -1, 0, 0, -1 ], [ 2, 2, -1, -1, 0, -1 ], [ 0, 2, -1, 0, 0, -1 ], [ 1, 2, -1, 0, 0, -2 ] ], - [ [ -2, 2, -1, 0, 0, 0 ], [ 2, 2, -1, -1, 0, -1 ], [ 0, 2, -1, 0, 0, -1 ], [ 1, 2, -1, 0, 0, -2 ] ], - [ [ -1, 2, -2, 0, 0, -1 ], [ 2, 2, -1, -1, 0, -1 ], [ 0, 2, -1, 0, 0, -1 ], [ 1, 2, -1, 0, 0, -2 ] ], - [ [ -2, 2, -1, 1, 0, -1 ], [ 2, 2, -1, -1, 0, -1 ], [ 0, 2, -1, 0, 0, -1 ], [ 1, 2, -1, 0, 0, -2 ] ] -], -"cur_uid": "449aeaa6", -"ref_uid": "628d5c8b", -"order_seed": 338959, -"dur_seed": 810921, -"motifs_seed": 154723, -"entrances_probs_vals": [ 0.29, 0, 7.0238095238095, 0.77, 2.1703296703297, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"passages_probs_vals": [ 0.29, 0, 7.0238095238095, 0.77, 2.1703296703297, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0.29, 0, 7.0238095238095, 0.77, 2.1703296703297, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ -3600, -349 ], [ 799, 1758 ], [ -282, 1013 ], [ -282, 799 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 2 ], [ 1, 3, 0, 3, 0, 0, 1, 1, 0, 1 ], [ ] ], - [ [ 2 ], [ 0, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 2, 2, 2, 2 ], [ 1, 3 ] ], - [ [ 2 ], [ 1, 3, 0, 0, 1 ], [ ] ], - [ [ 2 ], [ 0, 0, 0, 0, 0 ], [ 1, 3 ] ] -], -"sus_weights": [ 0.75, 0.34, 0 ], -"order_size": [ 2, 6 ], -"passages_size": [ 0, 10 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/46210507/46210507_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/46210507/46210507_code.scd deleted file mode 100644 index a4e8b56..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/46210507/46210507_code.scd +++ /dev/null @@ -1,907 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1, 3)}, {rrand(0.3, 0.5)}); - }); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - ledger = ledger.drop(-1).add(curUID); - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, attack, release = 1, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = 30; - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * amp * EnvGen.kr(Env.adsr(attack, 0.3, 0.9, release, 0.9, -3), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); - //Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.sine(dur), gate, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs, hierarchicalDust; - - hierarchicalDust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) - ); - - sigs = [~stringModelBusArray, ~sineBusArray, ~bassBusArray, ~hdustBusArray, ~samplerBusArray].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -mixer = Synth.tail(~group, \mixer); -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/46210507/46210507_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/46210507/46210507_mus_model.json deleted file mode 100644 index 3ec4056..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/46210507/46210507_mus_model.json +++ /dev/null @@ -1,59 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 2.375 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ] ], 1.625 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ] ], 1.125 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 3 ] - ], - [ - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 3.125 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 1.125 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ -1, 0, 0, 0, 0, 1 ] ], 1.25 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ -1, 0, 0, 0, 0, 1 ] ], 1.375 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ] ], 1.5 ], - [ [ [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ] ], 0.875 ], - [ [ [ -1, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ] ], 2 ] - ], - [ - [ [ [ -1, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ "Rest" ] ], 1 ], - [ [ [ -1, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ "Rest" ] ], 1.375 ], - [ [ [ -1, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ "Rest" ] ], 1.75 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ "Rest" ] ], 1.375 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 1.625 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 2.375 ] - ] - ] -], -"last_changes": -[ - [ [ -1, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ] ], - [ [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ] ], - [ [ -1, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ] ], - [ [ -1, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ] ], - [ [ -1, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 0, -1, 0, 0, 0 ] ] -], -"cur_uid": "46210507", -"ref_uid": "nil", -"order_seed": 944186, -"dur_seed": 424778, -"motifs_seed": 515266, -"entrances_probs_vals": [ 0, 0.48, 1.7460317460317, 0.58, 1.68, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"passages_probs_vals": [ 0, 0.48, 1.7460317460317, 0.58, 1.68, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0, 0.48, 1.7460317460317, 0.58, 1.68, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ -3600, -627.86377708978 ], [ -3600, 260 ], [ -980.80495356037, 2066 ], [ -627.86377708978, 2053 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 2 ], [ 3, 3, 3 ], [ 0, 1 ] ], - [ [ 1 ], [ 2, 3, 0, 3, 0, 0 ], [ ] ], - [ [ 0, 1 ], [ 2, 2 ], [ 3 ] ] -], -"sus_weights": [ 0.73, 0.49, 0 ], -"order_size": [ 1, 7 ], -"passages_size": [ 0, 5 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/4b96f62d/4b96f62d_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/4b96f62d/4b96f62d_code.scd deleted file mode 100644 index 3ec9b1a..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/4b96f62d/4b96f62d_code.scd +++ /dev/null @@ -1,907 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1, 3)}, {rrand(0.3, 0.5)}); - }); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - ledger = ledger.drop(-1).add(curUID); - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, attack, release = 1, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = rrand(20, 40); - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - //sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * amp * EnvGen.kr(Env.adsr(attack, 0.3, 0.9, release, 0.9, -3), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); - //Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.sine(dur), gate, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs, hierarchicalDust; - - hierarchicalDust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) - ); - - sigs = [~stringModelBusArray, ~sineBusArray, ~bassBusArray, ~hdustBusArray, ~samplerBusArray].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -mixer = Synth.tail(~group, \mixer); -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/4b96f62d/4b96f62d_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/4b96f62d/4b96f62d_mus_model.json deleted file mode 100644 index c8a77ec..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/4b96f62d/4b96f62d_mus_model.json +++ /dev/null @@ -1,48 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 7, -7, -4, 0, -1, -2 ], [ "Rest" ] ], 2.25 ], - [ [ [ "Rest" ], [ "Rest" ], [ 7, -7, -4, 0, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], 3.875 ], - [ [ [ 8, -7, -4, 1, -1, -2 ], [ "Rest" ], [ 7, -7, -4, 0, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], 1.125 ], - [ [ [ 8, -7, -4, 1, -1, -2 ], [ 7, -8, -4, 0, -1, -2 ], [ 7, -7, -4, 0, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], 6.5 ] - ], - [ - [ [ [ 8, -7, -4, 1, -1, -2 ], [ "Rest" ], [ 7, -7, -4, 0, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], 2 ], - [ [ [ 8, -7, -4, 1, -1, -2 ], [ "Rest" ], [ 6, -7, -3, 1, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], 7.125 ], - [ [ [ "Rest" ], [ "Rest" ], [ 6, -7, -3, 1, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ 6, -7, -3, 1, -1, -2 ], [ "Rest" ] ], 1.625 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 5.5 ] - ] - ] -], -"last_changes": -[ - [ [ 8, -6, -4, 0, -1, -2 ], [ 6, -5, -4, 0, -1, -3 ], [ 6, -5, -4, 0, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], - [ [ 8, -6, -4, 0, -1, -2 ], [ 6, -5, -4, 0, -1, -3 ], [ 7, -7, -4, 0, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], - [ [ 8, -7, -4, 1, -1, -2 ], [ 6, -5, -4, 0, -1, -3 ], [ 7, -7, -4, 0, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], - [ [ 8, -7, -4, 1, -1, -2 ], [ 7, -8, -4, 0, -1, -2 ], [ 7, -7, -4, 0, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], - [ [ 8, -7, -4, 1, -1, -2 ], [ 7, -8, -4, 0, -1, -2 ], [ 6, -7, -3, 1, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ] -], -"cur_uid": "4b96f62d", -"ref_uid": "703e109b", -"order_seed": 550421, -"dur_seed": 808010, -"motifs_seed": 180604, -"entrances_probs_vals": [ 0.52, 0.56, 5.1984126984127, 0.76923076923077, 2.31, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"passages_probs_vals": [ 0.52, 0.56, 5.1984126984127, 0.76923076923077, 2.31, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0.52, 0.56, 5.1984126984127, 0.76923076923077, 2.31, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ 1211.1455108359, 2400 ], [ -1650, 450 ], [ -405, 1137 ], [ 951.08359133127, 2053 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 3, 0 ], [ 2 ], [ 1 ] ] -], -"sus_weights": [ 0.73, 0.49, 0 ], -"order_size": [ 1, 3 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/50fec831/50fec831_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/50fec831/50fec831_code.scd deleted file mode 100644 index ab370bd..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/50fec831/50fec831_code.scd +++ /dev/null @@ -1,887 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - lastXChanges = if(refUID == nil, { - [initVoices.value().deepCopy]; - }, { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - ledger = ledger.drop(-1).add(curUID); - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - player.stop; - group.set(\gate, 0); - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = 30; - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs, hierarchicalDust; - - hierarchicalDust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) - ); - - sigs = [~stringModelBusArray, ~sineBusArray, ~bassBusArray, ~hdustBusArray, ~samplerBusArray].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -mixer = Synth.tail(~group, \mixer); -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/50fec831/50fec831_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/50fec831/50fec831_mus_model.json deleted file mode 100644 index e3299cd..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/50fec831/50fec831_mus_model.json +++ /dev/null @@ -1,51 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 0, 1, 0, 0, 0, 0 ] ], 4.5 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ "Rest" ], [ 0, 1, 0, 0, 0, 0 ] ], 0.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 1 ], [ "Rest" ], [ 0, 1, 0, 0, 0, 0 ] ], 4.25 ] - ], - [ - [ [ [ 0, 1, 0, 0, 0, -1 ], [ -1, 1, 0, 0, 0, 1 ], [ "Rest" ], [ 0, 1, 0, 0, 0, 0 ] ], 0.75 ], - [ [ [ 0, 1, 0, 0, 0, -1 ], [ -1, 1, 0, 1, 0, 0 ], [ "Rest" ], [ 0, 1, 0, 0, 0, 0 ] ], 0.625 ], - [ [ [ 0, 1, 0, 0, 0, -1 ], [ -1, 1, 0, 1, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 0.75 ], - [ [ [ -1, 1, 0, 0, 1, 0 ], [ -1, 1, 0, 1, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 4.875 ], - [ [ [ -1, 1, 0, 0, 1, 0 ], [ "Rest" ], [ 0, 1, 1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 1, 0, 0, 1, 0 ], [ "Rest" ], [ 0, 1, 1, 0, 0, 0 ], [ "Rest" ] ], 1 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, 1, 0, 0, 0 ], [ "Rest" ] ], 1 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3.125 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 1 ], [ 1, -1, 1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], - [ [ 0, 1, 0, 0, 0, -1 ], [ -1, 1, 0, 0, 0, 1 ], [ 1, -1, 1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], - [ [ 0, 1, 0, 0, 0, -1 ], [ -1, 1, 0, 1, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], - [ [ 0, 1, 0, 0, 0, -1 ], [ -1, 1, 0, 1, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], - [ [ -1, 1, 0, 0, 1, 0 ], [ -1, 1, 0, 1, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ] -], -"cur_uid": "50fec831", -"ref_uid": "7264e3ac", -"order_seed": 982967, -"dur_seed": 762088, -"motifs_seed": 404006, -"entrances_probs_vals": [ 0, 1.67, 4.8015873015873, 0.24725274725275, 1.15, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"passages_probs_vals": [ 0, 1.67, 4.8015873015873, 0.24725274725275, 1.15, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0, 1.67, 4.8015873015873, 0.24725274725275, 1.15, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ -1100, 460.68111455108 ], [ -507, 1084.8297213622 ], [ 884.21052631579, 2237 ], [ 1040.2476780186, 2053 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 0, 3 ], [ 1, 1 ], [ 2 ] ], - [ [ 3 ], [ 0, 1, 2, 0 ], [ ] ] -], -"sus_weights": [ 0.73, 0.23, 0 ], -"order_size": [ 1, 3 ], -"passages_size": [ 0, 2 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/5267b235/5267b235_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/5267b235/5267b235_code.scd deleted file mode 100644 index ab370bd..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/5267b235/5267b235_code.scd +++ /dev/null @@ -1,887 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - lastXChanges = if(refUID == nil, { - [initVoices.value().deepCopy]; - }, { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - ledger = ledger.drop(-1).add(curUID); - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - player.stop; - group.set(\gate, 0); - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = 30; - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs, hierarchicalDust; - - hierarchicalDust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) - ); - - sigs = [~stringModelBusArray, ~sineBusArray, ~bassBusArray, ~hdustBusArray, ~samplerBusArray].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -mixer = Synth.tail(~group, \mixer); -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/5267b235/5267b235_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/5267b235/5267b235_mus_model.json deleted file mode 100644 index 56ea9be..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/5267b235/5267b235_mus_model.json +++ /dev/null @@ -1,43 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 2.25 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1.75 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 3.125 ], - [ [ [ 2, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 2.625 ], - [ [ [ 2, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 3 ], - [ [ [ 2, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1.25 ], - [ [ [ 2, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 2.75 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 2.75 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.5 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 2, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 2, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ] -], -"cur_uid": "5267b235", -"ref_uid": "nil", -"order_seed": 474005, -"dur_seed": 826425, -"motifs_seed": 116157, -"entrances_probs_vals": [ 0, 0, 1.984126984127, 0, 3.0769230769231, 0, 0.64527027027027, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 1.984126984127, 0, 3.0769230769231, 0, 0.64527027027027, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 1.984126984127, 0, 3.0769230769231, 0, 0.64527027027027, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ 1419.1950464396, 2400 ], [ 1519.5046439628, 2400 ], [ 1541.7956656347, 2237 ], [ 1519.5046439628, 2053 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 2, 1, 3 ], [ 0, 0 ], [ ] ] -], -"sus_weights": [ 0.75, 0.69, 0.75 ], -"order_size": [ 1, 2 ], -"passages_size": [ 0, 2 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/5625a95a/5625a95a_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/5625a95a/5625a95a_code.scd deleted file mode 100644 index ab370bd..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/5625a95a/5625a95a_code.scd +++ /dev/null @@ -1,887 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - lastXChanges = if(refUID == nil, { - [initVoices.value().deepCopy]; - }, { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - ledger = ledger.drop(-1).add(curUID); - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - player.stop; - group.set(\gate, 0); - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = 30; - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs, hierarchicalDust; - - hierarchicalDust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) - ); - - sigs = [~stringModelBusArray, ~sineBusArray, ~bassBusArray, ~hdustBusArray, ~samplerBusArray].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -mixer = Synth.tail(~group, \mixer); -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/5625a95a/5625a95a_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/5625a95a/5625a95a_mus_model.json deleted file mode 100644 index 2bd7c20..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/5625a95a/5625a95a_mus_model.json +++ /dev/null @@ -1,43 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 0.125 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 3.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, 0, 0, -1 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 4.125 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 2.375 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0.25 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 2.75 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, 0, 0, -1 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ] -], -"cur_uid": "5625a95a", -"ref_uid": "nil", -"order_seed": 871476, -"dur_seed": 417039, -"motifs_seed": 168381, -"entrances_probs_vals": [ 0, 0, 1.984126984127, 0, 3.0769230769231, 0, 0.64527027027027, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 1.984126984127, 0, 3.0769230769231, 0, 0.64527027027027, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 1.984126984127, 0, 3.0769230769231, 0, 0.64527027027027, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ 1419.1950464396, 2400 ], [ 1519.5046439628, 2400 ], [ 1541.7956656347, 2237 ], [ 1519.5046439628, 2053 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 0, 3, 1 ], [ 2, 2 ], [ ] ] -], -"sus_weights": [ 0.75, 0.69, 0.75 ], -"order_size": [ 1, 2 ], -"passages_size": [ 0, 2 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/628d5c8b/628d5c8b_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/628d5c8b/628d5c8b_code.scd deleted file mode 100644 index 90f0b1e..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/628d5c8b/628d5c8b_code.scd +++ /dev/null @@ -1,741 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON; - -// model vars -//(model and global vars mostly set by OSC funcs -var curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, orders, susWeights, passagesWeights, passagesSize, orderSize; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var lastXChanges, popSize, exPath, dir, primes, dims, tuples, -seq, group, player, ledgerPath, ledger, currentlyPlayingUID; - - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, min, max, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - durFunc = {arg allowChord; - var res; - res = if(allowChord.not, { - pTable.tableRand * (max - min) + min - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (max - min) + min}); - }).round(0.125); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - allowChord = if((sus ++ silent).includes(ins), { - //(sus ++ silent).includes(ins) && (ins != sus.last); - ins != sus.last; - }, { - if(i < (flatOrder.size - 1), {(isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not}, {false}); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord); - }, { - dur = passagesDurFunc.value(allowChord); - }); - //dur = passagesDurFunc.value(allowChord); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - dur = exitsDurFunc.value(allowChord); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr; - var voices, durs, patterns, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - res = Ppar( - voices.flop.collect({arg voice; - var clumps, hdScores, freqs, fDurs; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \instrument, \test, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1) - ) - }) ++ - [ - Pbind( - \type, \osc, - \addr, addr, - //\indexPath, "/cur_play_index", - //\indexMsg, Pseq(indices, 1), - //\seqPath, "/mus_seq", - //\seqMsg, Pseq(seq, 1), - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - ); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path; - var file, nameSpaces, modelItems, resString; - file = File(path,"w"); - - nameSpaces = [ - "music_data", "last_changes", - "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size" - ]; - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize - ]; - - resString = [nameSpaces, modelItems].flop.collect({arg item; - var nameSpace, modelItem, depth = 0, insert = " "; - # nameSpace, modelItem = item; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (modelItem == nil), {modelItem = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(modelItem, depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var nameSpaces, data; - - //model = File(path, "r").readAllString.parseJSON; - - nameSpaces = [ - "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size" - ]; - - data = nameSpaces.collect({arg nS; msgInterpret.value(jsonObject[nS])}); - - //data.postln; - - # curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize = data; - - popSize = ranges.size; -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - loadModelFile.value(msg[1].asString); -}, \load_model); - - -OSCdef(\generate, {arg msg, time, addr, port; - var path, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - loadModelFile.value(path); - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - lastXChanges = if(refUID == nil, { - [initVoices.value().deepCopy]; - }, { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..2] ++ [entrancesProbVals[3..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..2] ++ [passagesProbVals[3..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..2] ++ [exitsProbVals[3..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - modelString = writeResources.value(path); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var newLedger, modelPath, musString, musFile, test1, test2; - msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - curUID = genUID.value; - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - writeResources.value(modelPath); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - newLedger = File(ledgerPath, "w"); - ledger = ledger.drop(-1).add(curUID); - newLedger.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - newLedger.close; - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - player.stop; - group.set(\gate, 0); - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms; - noHarms = 30; - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) - -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) - - - -"{\"a\": 1}".parseYAML["a"].asInteger; -"{\"a\": 1}".parseJSON["a"].isNumber; - -1223423434123.asHexString.toLower - -Date.getDate.rawSeconds -Date.seed.asHexString.toLower - -n = NetAddr("localhost", 8080); -n.sendMsg("/GET/#", (NetAddr.localAddr.hostname ++ ":" ++ NetAddr.localAddr.port), "/passage_probs_vals"); \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/628d5c8b/628d5c8b_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/628d5c8b/628d5c8b_mus_model.json deleted file mode 100644 index a7c647e..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/628d5c8b/628d5c8b_mus_model.json +++ /dev/null @@ -1,56 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 0, 1, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 1, 0, 0, 0, 0 ] ], 1.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, -1, 0 ] ], 1.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 0, 0, 0, 1, 0 ] ], 1.5 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 0, 1, 0, 0, 0 ] ], 0.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, -1, 0, 0 ] ], 1.25 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ], [ -1, 0, 0, 1, 0, 0 ] ], 1.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 1, 0, 0, 0, 0 ] ], 1.875 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1.125 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 0.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, -1, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1.5 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 1 ], [ 0, 1, 0, 0, 0, 0 ] ], 1.5 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, -1 ], [ 0, 1, 0, 0, 0, 0 ] ], 1.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 1, 0, 0, 0, 0 ] ], 1.125 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0.5 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.25 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, -1, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 1 ], [ 0, 1, 0, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, -1 ], [ 0, 1, 0, 0, 0, 0 ] ] -], -"cur_uid": "628d5c8b", -"ref_uid": "7e170ef8", -"order_seed": 227004, -"dur_seed": 357129, -"motifs_seed": 170994, -"entrances_probs_vals": [ 0.75, 0.5, 2, 0, 0.5, 0.26424870466321, 0.75675675675676, 0.5, 0.5, 0.58549222797927, 0.72635135135135, 1, 0.5 ], -"passages_probs_vals": [ 0.75, 0.5, 2, 0, 0.5, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0.75, 0.5, 2, 0, 0.5, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ 65, 727 ], [ 799, 1758 ], [ -282, 1013 ], [ -282, 799 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 0 ], [ 3, 2, 3, 3, 3, 3, 3, 3 ], [ 1 ] ], - [ [ 0, 3, 1 ], [ 2, 2, 2, 2, 2 ], [ ] ] -], -"sus_weights": [ 0.75, 0.69, 0.75 ], -"order_size": [ 2, 6 ], -"passages_size": [ 0, 10 ] -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/6409252e/6409252e_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/6409252e/6409252e_code.scd deleted file mode 100644 index 3ec9b1a..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/6409252e/6409252e_code.scd +++ /dev/null @@ -1,907 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1, 3)}, {rrand(0.3, 0.5)}); - }); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - ledger = ledger.drop(-1).add(curUID); - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, attack, release = 1, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = rrand(20, 40); - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - //sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * amp * EnvGen.kr(Env.adsr(attack, 0.3, 0.9, release, 0.9, -3), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); - //Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.sine(dur), gate, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs, hierarchicalDust; - - hierarchicalDust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) - ); - - sigs = [~stringModelBusArray, ~sineBusArray, ~bassBusArray, ~hdustBusArray, ~samplerBusArray].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -mixer = Synth.tail(~group, \mixer); -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/6409252e/6409252e_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/6409252e/6409252e_mus_model.json deleted file mode 100644 index 50778fb..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/6409252e/6409252e_mus_model.json +++ /dev/null @@ -1,49 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ -2, 3, -2, 1, 1, 1 ], [ "Rest" ], [ "Rest" ] ], 0.125 ], - [ [ [ -5, 3, -2, 2, 1, 1 ], [ -2, 3, -2, 1, 1, 1 ], [ "Rest" ], [ "Rest" ] ], 0.5 ], - [ [ [ -5, 3, -2, 2, 1, 1 ], [ -2, 3, -2, 1, 1, 1 ], [ "Rest" ], [ -4, 5, -2, 2, 2, -1 ] ], 0.625 ], - [ [ [ -5, 3, -2, 2, 1, 1 ], [ -2, 3, -2, 1, 1, 1 ], [ -2, 2, -2, 1, 1, 1 ], [ -4, 5, -2, 2, 2, -1 ] ], 5.625 ] - ], - [ - [ [ [ -5, 3, -2, 2, 1, 1 ], [ -2, 3, -2, 1, 1, 1 ], [ -3, 4, -2, 2, 2, -1 ], [ -4, 5, -2, 2, 2, -1 ] ], 1.125 ], - [ [ [ -5, 3, -2, 2, 1, 1 ], [ -3, 3, -1, 2, 1, 1 ], [ -3, 4, -2, 2, 2, -1 ], [ -4, 5, -2, 2, 2, -1 ] ], 2.5 ], - [ [ [ -5, 3, -2, 2, 1, 1 ], [ -3, 3, -1, 2, 1, 1 ], [ -3, 4, -2, 2, 2, -1 ], [ "Rest" ] ], 1.375 ], - [ [ [ "Rest" ], [ -3, 3, -1, 2, 1, 1 ], [ -3, 4, -2, 2, 2, -1 ], [ "Rest" ] ], 0.75 ], - [ [ [ "Rest" ], [ "Rest" ], [ -3, 4, -2, 2, 2, -1 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.125 ] - ] - ] -], -"last_changes": -[ - [ [ -5, 3, -2, 2, 1, 1 ], [ -4, 5, -2, 3, 2, -1 ], [ -4, 3, -2, 3, 1, 1 ], [ -4, 5, -2, 2, 2, -1 ] ], - [ [ -5, 3, -2, 2, 1, 1 ], [ -2, 3, -2, 1, 1, 1 ], [ -4, 3, -2, 3, 1, 1 ], [ -4, 5, -2, 2, 2, -1 ] ], - [ [ -5, 3, -2, 2, 1, 1 ], [ -2, 3, -2, 1, 1, 1 ], [ -2, 2, -2, 1, 1, 1 ], [ -4, 5, -2, 2, 2, -1 ] ], - [ [ -5, 3, -2, 2, 1, 1 ], [ -2, 3, -2, 1, 1, 1 ], [ -3, 4, -2, 2, 2, -1 ], [ -4, 5, -2, 2, 2, -1 ] ], - [ [ -5, 3, -2, 2, 1, 1 ], [ -3, 3, -1, 2, 1, 1 ], [ -3, 4, -2, 2, 2, -1 ], [ -4, 5, -2, 2, 2, -1 ] ] -], -"cur_uid": "6409252e", -"ref_uid": "tmp", -"order_seed": 825836, -"dur_seed": 453411, -"motifs_seed": 115471, -"entrances_probs_vals": [ 0.29, 0, 1.3492063492064, 0, 0.65934065934066, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"passages_probs_vals": [ 0.29, 0, 5, 0.58, 1.7582417582418, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0.29, 0, 5, 0.58, 1.7582417582418, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ -3600, -349 ], [ 799, 1758 ], [ -282, 1013 ], [ -282, 799 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 3, 0 ], [ 2, 1 ], [ ] ] -], -"sus_weights": [ 0.39, 0.32, 0.77 ], -"order_size": [ 1, 3 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/6a3f7c7c/6a3f7c7c_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/6a3f7c7c/6a3f7c7c_code.scd deleted file mode 100644 index ab370bd..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/6a3f7c7c/6a3f7c7c_code.scd +++ /dev/null @@ -1,887 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - lastXChanges = if(refUID == nil, { - [initVoices.value().deepCopy]; - }, { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - ledger = ledger.drop(-1).add(curUID); - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - player.stop; - group.set(\gate, 0); - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = 30; - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs, hierarchicalDust; - - hierarchicalDust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) - ); - - sigs = [~stringModelBusArray, ~sineBusArray, ~bassBusArray, ~hdustBusArray, ~samplerBusArray].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -mixer = Synth.tail(~group, \mixer); -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/6a3f7c7c/6a3f7c7c_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/6a3f7c7c/6a3f7c7c_mus_model.json deleted file mode 100644 index 829f700..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/6a3f7c7c/6a3f7c7c_mus_model.json +++ /dev/null @@ -1,43 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 2, -1, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 2.75 ], - [ [ [ 2, -1, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 4.5 ], - [ [ [ 2, -1, 0, 0, 0, 0 ], [ "Rest" ], [ 2, 0, 0, 0, 0, -1 ], [ 0, 0, 0, 0, 0, 0 ] ], 2.25 ], - [ [ [ 2, -1, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 3.5 ], - [ [ [ "Rest" ], [ "Rest" ], [ 1, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 2.25 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 0.125 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 2, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 2, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 2, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, 0, 0, -1 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 2, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ] -], -"cur_uid": "6a3f7c7c", -"ref_uid": "5267b235", -"order_seed": 857701, -"dur_seed": 870436, -"motifs_seed": 456020, -"entrances_probs_vals": [ 0, 0, 1.984126984127, 0, 3.0769230769231, 0, 0.64527027027027, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 1.984126984127, 0, 3.0769230769231, 0, 0.64527027027027, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 1.984126984127, 0, 3.0769230769231, 0, 0.64527027027027, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ 1419.1950464396, 2400 ], [ 1519.5046439628, 2400 ], [ 1541.7956656347, 2237 ], [ 1519.5046439628, 2053 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 0, 3 ], [ 2, 2 ], [ 1 ] ] -], -"sus_weights": [ 0.75, 0.69, 0.75 ], -"order_size": [ 1, 2 ], -"passages_size": [ 0, 2 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/6abf27d4/6abf27d4_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/6abf27d4/6abf27d4_code.scd deleted file mode 100644 index 127f295..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/6abf27d4/6abf27d4_code.scd +++ /dev/null @@ -1,808 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr; - var voices, durs, patterns, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - res = Ppar( - voices.flop.collect({arg voice; - var clumps, hdScores, freqs, fDurs; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \instrument, \test, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1) - ) - }) ++ - [ - Pbind( - \type, \osc, - \addr, addr, - //\indexPath, "/cur_play_index", - //\indexMsg, Pseq(indices, 1), - //\seqPath, "/mus_seq", - //\seqMsg, Pseq(seq, 1), - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - ); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -/* -writeResources = {arg path; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = [nameSpaces, modelItems].flop.collect({arg item; - var nameSpace, modelItem, depth = 0, insert = " "; - # nameSpace, modelItem = item; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (modelItem == nil), {modelItem = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(modelItem, depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; -*/ - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - //model = File(path, "r").readAllString.parseJSON; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - lastXChanges = if(refUID == nil, { - [initVoices.value().deepCopy]; - }, { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - dict.postln; - musicChanged = (musicData != seq).postln; - - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, {dict["motif_edited"] = "true"}); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - newLedger = File(ledgerPath, "w"); - ledger = ledger.drop(-1).add(curUID); - newLedger.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - newLedger.close; - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - player.stop; - group.set(\gate, 0); - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms; - noHarms = 30; - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; -) - -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) - - - -"{\"a\": 1}".parseYAML["a"].asInteger; -"{\"a\": 1}".parseJSON["a"].isNumber; - -1223423434123.asHexString.toLower - -Date.getDate.rawSeconds -Date.seed.asHexString.toLower - -n = NetAddr("localhost", 8080); -n.sendMsg("/GET/#", (NetAddr.localAddr.hostname ++ ":" ++ NetAddr.localAddr.port), "/passage_probs_vals"); \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/6abf27d4/6abf27d4_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/6abf27d4/6abf27d4_mus_model.json deleted file mode 100644 index 818ccbc..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/6abf27d4/6abf27d4_mus_model.json +++ /dev/null @@ -1,93 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 8.375 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.5 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 10.75 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, -1 ], [ -1, 0, 0, 1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, -1 ], [ -1, 0, 0, 1, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 1.25 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, -1 ], [ 0, 0, -1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 1.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, -1 ], [ 0, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, -1 ], [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 1, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 1, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 1, 0 ] ], 1.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 1, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 8 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, -1, 0, 1, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, -1, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 1.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 0, 0, 0, 1, 1 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 1.25 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 1, 0, 0, 1, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 8.625 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 1, 0, 0, 1, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ] ], 1.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 1, 0, 0, 1, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 1, 1, 0, -1, 0, 0 ] ], 1.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 1, 0, 0, 1, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 1, 0 ] ], 0.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 1, 0, 0, 1, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 0.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 1, 0, 0, 1, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 2, 0 ] ], 9.25 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 1, 0, 0, 1, 0 ], [ -1, 0, 0, 0, 1, 0 ], [ -1, 1, 0, 0, 2, 0 ] ], 1.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 1, 0, 0, 1, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ -1, 1, 0, 0, 2, 0 ] ], 1.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 1, 0, 0, 1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ -1, 1, 0, 0, 2, 0 ] ], 1.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 1, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 2, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 1, 0, 0, 1, 0 ], [ -1, 1, 0, 0, 1, -1 ], [ -1, 1, 0, 0, 2, 0 ] ], 9.75 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ -1, 1, 0, 0, 1, -1 ], [ -1, 1, 0, 0, 2, 0 ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ -1, 1, 0, 0, 1, -1 ], [ -1, 1, 0, 0, 2, 0 ] ], 1.25 ], - [ [ [ "Rest" ], [ "Rest" ], [ -3, 1, 0, 0, 2, 1 ], [ -1, 1, 0, 0, 2, 0 ] ], 1.875 ], - [ [ [ "Rest" ], [ "Rest" ], [ -3, 2, 0, 0, 2, 0 ], [ -1, 1, 0, 0, 2, 0 ] ], 1.25 ], - [ [ [ "Rest" ], [ "Rest" ], [ -2, 1, -1, 0, 2, 0 ], [ -1, 1, 0, 0, 2, 0 ] ], 2 ], - [ [ [ "Rest" ], [ "Rest" ], [ -3, 1, 0, 1, 2, 0 ], [ -1, 1, 0, 0, 2, 0 ] ], 7.625 ], - [ [ [ "Rest" ], [ "Rest" ], [ -3, 1, 0, 1, 2, 0 ], [ "Rest" ] ], 1 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 8.375 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 1, 0, 0, 1, 0 ], [ -1, 1, 0, 0, 1, -1 ], [ -1, 1, 0, 0, 2, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 1, 0, 0, 1, 0 ], [ -3, 1, 0, 0, 2, 1 ], [ -1, 1, 0, 0, 2, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 1, 0, 0, 1, 0 ], [ -3, 2, 0, 0, 2, 0 ], [ -1, 1, 0, 0, 2, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 1, 0, 0, 1, 0 ], [ -2, 1, -1, 0, 2, 0 ], [ -1, 1, 0, 0, 2, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 1, 0, 0, 1, 0 ], [ -3, 1, 0, 1, 2, 0 ], [ -1, 1, 0, 0, 2, 0 ] ] -], -"cur_uid": "6abf27d4", -"ref_uid": "nil", -"order_seed": 587621, -"dur_seed": 706606, -"motifs_seed": 392608, -"entrances_probs_vals": [ 0.34, 6.468253968254, 9.2857142857143, 0.5, 2, 0, 0.5, 0.24509803921569, 0.89189189189189, 0.5, 1, 0.5, 0.5, 0.8562091503268, 0.69932432432432, 1, 0.5 ], -"passages_probs_vals": [ 0.34, 6.468253968254, 9.2857142857143, 0.5, 2, 0, 0.5, 0.24509803921569, 0.89189189189189, 0.5, 1, 0.5, 0.5, 0.8562091503268, 0.69932432432432, 1, 0.5 ], -"exits_probs_vals": [ 0.34, 6.468253968254, 9.2857142857143, 0.5, 2, 0, 0.5, 0.24509803921569, 0.89189189189189, 0.5, 1, 0.5, 0.5, 0.8562091503268, 0.69932432432432, 1, 0.5 ], -"ranges": [ [ -1200, 2400 ], [ -1200, 2400 ], [ -1200, 2400 ], [ -1200, 2400 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 0, 2, 3 ], [ 1, 1, 1, 1, 1 ], [ ] ], - [ [ 0 ], [ 3, 2, 1, 1, 3, 2, 3, 2, 1, 2 ], [ ] ], - [ [ 0, 3, 2 ], [ 1, 1, 1, 1, 1, 1 ], [ ] ], - [ [ 1, 2, 0 ], [ 3, 3, 3, 3, 3 ], [ ] ], - [ [ 1, 3, 0 ], [ 2, 2, 2, 2, 2 ], [ ] ], - [ [ 3 ], [ 2, 2, 2, 2 ], [ 1, 0 ] ] -], -"sus_weights": [ 0.75, 0.75, 0.75 ], -"order_size": [ 1, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/6d0c2f19/6d0c2f19_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/6d0c2f19/6d0c2f19_code.scd deleted file mode 100644 index ab370bd..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/6d0c2f19/6d0c2f19_code.scd +++ /dev/null @@ -1,887 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - lastXChanges = if(refUID == nil, { - [initVoices.value().deepCopy]; - }, { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - ledger = ledger.drop(-1).add(curUID); - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - player.stop; - group.set(\gate, 0); - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = 30; - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs, hierarchicalDust; - - hierarchicalDust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) - ); - - sigs = [~stringModelBusArray, ~sineBusArray, ~bassBusArray, ~hdustBusArray, ~samplerBusArray].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -mixer = Synth.tail(~group, \mixer); -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/6d0c2f19/6d0c2f19_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/6d0c2f19/6d0c2f19_mus_model.json deleted file mode 100644 index a36e0d1..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/6d0c2f19/6d0c2f19_mus_model.json +++ /dev/null @@ -1,44 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 2, 0, 0, -1, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 2, 0, 0, -1, 0, 0 ] ], 0.375 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ], [ 2, 0, 0, -1, 0, 0 ] ], 4.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 2, 0, 0, -1, 0, 0 ] ], 2.375 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ "Rest" ] ], 0.375 ], - [ [ [ "Rest" ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ "Rest" ] ], 0.375 ], - [ [ [ "Rest" ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3.875 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, -1, 0, 0, 0, 1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 2, 0, 0, -1, 0, 0 ] ] -], -"cur_uid": "6d0c2f19", -"ref_uid": "7e170ef8", -"order_seed": 861383, -"dur_seed": 654405, -"motifs_seed": 513928, -"entrances_probs_vals": [ 0.75, 1.67, 4.8015873015873, 0, 0.5, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"passages_probs_vals": [ 0.75, 1.67, 4.8015873015873, 0, 0.5, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0.75, 1.87, 5.1984126984127, 0, 0.5, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ -384, 2400 ], [ -507, 2400 ], [ -282, 2237 ], [ -1200, 2053 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 3, 0, 1 ], [ 2 ], [ ] ] -], -"sus_weights": [ 0.75, 0.69, 0.75 ], -"order_size": [ 1, 2 ], -"passages_size": [ 0, 1 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/6d743c5c/6d743c5c_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/6d743c5c/6d743c5c_code.scd deleted file mode 100644 index 1b05aa0..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/6d743c5c/6d743c5c_code.scd +++ /dev/null @@ -1,881 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - lastXChanges = if(refUID == nil, { - [initVoices.value().deepCopy]; - }, { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - ledger = ledger.drop(-1).add(curUID); - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - player.stop; - group.set(\gate, 0); - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = 30; - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * EnvGen.kr(Env.asr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs; - - sigs = [~stringModelBusArray, ~sineBusArray, ~bassBusArray, ~hdustBusArray, ~samplerBusArray].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -mixer = Synth.tail(~group, \mixer); -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/6d743c5c/6d743c5c_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/6d743c5c/6d743c5c_mus_model.json deleted file mode 100644 index b1611ee..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/6d743c5c/6d743c5c_mus_model.json +++ /dev/null @@ -1,41 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.375 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, 0, 0, -1 ] ], 3.375 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, 0, 0, -1 ] ], 0.25 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, 0, 0, -1 ] ], 2 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 2.25 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 2.125 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, 0, 0, -1 ] ] -], -"cur_uid": "6d743c5c", -"ref_uid": "nil", -"order_seed": 232987, -"dur_seed": 390795, -"motifs_seed": 257319, -"entrances_probs_vals": [ 0, 0, 1.984126984127, 0, 3.0769230769231, 0, 0.64527027027027, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 1.984126984127, 0, 3.0769230769231, 0, 0.64527027027027, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 1.984126984127, 0, 3.0769230769231, 0, 0.64527027027027, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ 1419.1950464396, 2400 ], [ 1519.5046439628, 2400 ], [ 1541.7956656347, 2237 ], [ 1519.5046439628, 2053 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 0, 1, 2 ], [ 3 ], [ ] ] -], -"sus_weights": [ 0.75, 0.69, 0.75 ], -"order_size": [ 1, 2 ], -"passages_size": [ 0, 2 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/6f1305ed/6f1305ed_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/6f1305ed/6f1305ed_code.scd deleted file mode 100644 index 830a192..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/6f1305ed/6f1305ed_code.scd +++ /dev/null @@ -1,894 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - ledger = ledger.drop(-1).add(curUID); - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - player.stop; - group.set(\gate, 0); - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = 30; - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs, hierarchicalDust; - - hierarchicalDust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) - ); - - sigs = [~stringModelBusArray, ~sineBusArray, ~bassBusArray, ~hdustBusArray, ~samplerBusArray].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -mixer = Synth.tail(~group, \mixer); -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/6f1305ed/6f1305ed_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/6f1305ed/6f1305ed_mus_model.json deleted file mode 100644 index 89155f1..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/6f1305ed/6f1305ed_mus_model.json +++ /dev/null @@ -1,51 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 1, -1 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1 ], - [ [ [ 0, 0, 0, 0, 1, -1 ], [ 1, -1, 0, 0, 1, -1 ], [ "Rest" ], [ "Rest" ] ], 2.875 ], - [ [ [ 0, 0, 0, 0, 1, -1 ], [ 1, -1, 0, 0, 1, -1 ], [ "Rest" ], [ 2, -1, 0, 0, 1, -1 ] ], 3.75 ] - ], - [ - [ [ [ 0, 0, 0, 0, 1, -1 ], [ 1, -1, 0, 0, 1, -1 ], [ 2, 0, 0, 0, 1, -1 ], [ 2, -1, 0, 0, 1, -1 ] ], 2.875 ], - [ [ [ 0, 0, 0, 0, 1, -1 ], [ 0, 0, 1, 0, 1, -1 ], [ 2, 0, 0, 0, 1, -1 ], [ 2, -1, 0, 0, 1, -1 ] ], 1.75 ], - [ [ [ 0, 0, 0, 0, 1, -1 ], [ 0, 0, 1, 0, 1, -1 ], [ 2, 0, 0, 0, 1, -1 ], [ 1, 1, 0, 0, 1, -1 ] ], 1.875 ], - [ [ [ -1, 0, 0, 1, 1, -1 ], [ 0, 0, 1, 0, 1, -1 ], [ 2, 0, 0, 0, 1, -1 ], [ 1, 1, 0, 0, 1, -1 ] ], 1.75 ], - [ [ [ -1, 0, 0, 1, 1, -1 ], [ 1, 0, 0, -1, 1, -1 ], [ 2, 0, 0, 0, 1, -1 ], [ 1, 1, 0, 0, 1, -1 ] ], 2.75 ], - [ [ [ -1, 0, 0, 1, 1, -1 ], [ 1, 0, 0, -1, 1, -1 ], [ 2, 0, 0, 0, 1, -1 ], [ "Rest" ] ], 0.375 ], - [ [ [ -1, 0, 0, 1, 1, -1 ], [ 1, 0, 0, -1, 1, -1 ], [ "Rest" ], [ "Rest" ] ], 0.625 ], - [ [ [ "Rest" ], [ 1, 0, 0, -1, 1, -1 ], [ "Rest" ], [ "Rest" ] ], 0.5 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 4 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 1, -1 ], [ 1, -1, 0, 0, 1, -1 ], [ 2, 0, 0, 0, 1, -1 ], [ 2, -1, 0, 0, 1, -1 ] ], - [ [ 0, 0, 0, 0, 1, -1 ], [ 0, 0, 1, 0, 1, -1 ], [ 2, 0, 0, 0, 1, -1 ], [ 2, -1, 0, 0, 1, -1 ] ], - [ [ 0, 0, 0, 0, 1, -1 ], [ 0, 0, 1, 0, 1, -1 ], [ 2, 0, 0, 0, 1, -1 ], [ 1, 1, 0, 0, 1, -1 ] ], - [ [ -1, 0, 0, 1, 1, -1 ], [ 0, 0, 1, 0, 1, -1 ], [ 2, 0, 0, 0, 1, -1 ], [ 1, 1, 0, 0, 1, -1 ] ], - [ [ -1, 0, 0, 1, 1, -1 ], [ 1, 0, 0, -1, 1, -1 ], [ 2, 0, 0, 0, 1, -1 ], [ 1, 1, 0, 0, 1, -1 ] ] -], -"cur_uid": "6f1305ed", -"ref_uid": "tmp", -"order_seed": 414624, -"dur_seed": 257250, -"motifs_seed": 938764, -"entrances_probs_vals": [ 0, 1.11, 3.2936507936508, 0.85, 2.1153846153846, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"passages_probs_vals": [ 0, 1.11, 3.2936507936508, 0.85, 2.1153846153846, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0, 1.83, 4.8809523809524, 0.24725274725275, 1.15, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ -1100, 460.68111455108 ], [ -507, 1084.8297213622 ], [ 884.21052631579, 2237 ], [ 1040.2476780186, 2053 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 0, 1 ], [ 3 ], [ 2 ] ], - [ [ 2 ], [ 1, 3, 0, 1 ], [ ] ] -], -"sus_weights": [ 0.73, 0.23, 0 ], -"order_size": [ 2, 2 ], -"passages_size": [ 0, 2 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/703e109b/703e109b_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/703e109b/703e109b_code.scd deleted file mode 100644 index 3ec9b1a..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/703e109b/703e109b_code.scd +++ /dev/null @@ -1,907 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1, 3)}, {rrand(0.3, 0.5)}); - }); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - ledger = ledger.drop(-1).add(curUID); - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, attack, release = 1, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = rrand(20, 40); - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - //sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * amp * EnvGen.kr(Env.adsr(attack, 0.3, 0.9, release, 0.9, -3), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); - //Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.sine(dur), gate, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs, hierarchicalDust; - - hierarchicalDust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) - ); - - sigs = [~stringModelBusArray, ~sineBusArray, ~bassBusArray, ~hdustBusArray, ~samplerBusArray].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -mixer = Synth.tail(~group, \mixer); -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/703e109b/703e109b_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/703e109b/703e109b_mus_model.json deleted file mode 100644 index c0a214c..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/703e109b/703e109b_mus_model.json +++ /dev/null @@ -1,48 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 6, -5, -4, 0, -1, -2 ], [ "Rest" ] ], 0.875 ], - [ [ [ "Rest" ], [ "Rest" ], [ 6, -5, -4, 0, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], 3 ], - [ [ [ 8, -6, -4, 0, -1, -2 ], [ "Rest" ], [ 6, -5, -4, 0, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], 1.25 ], - [ [ [ 8, -6, -4, 0, -1, -2 ], [ 6, -5, -4, 0, -1, -3 ], [ 6, -5, -4, 0, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], 2 ] - ], - [ - [ [ [ 8, -6, -4, 0, -1, -2 ], [ "Rest" ], [ 6, -5, -4, 0, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], 0 ], - [ [ [ 8, -6, -4, 0, -1, -2 ], [ "Rest" ], [ 7, -7, -4, 0, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], 2.375 ], - [ [ [ 8, -6, -4, 0, -1, -2 ], [ "Rest" ], [ 7, -7, -4, 0, -1, -2 ], [ "Rest" ] ], 0.875 ], - [ [ [ "Rest" ], [ "Rest" ], [ 7, -7, -4, 0, -1, -2 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.625 ] - ] - ] -], -"last_changes": -[ - [ [ 7, -5, -3, 0, -1, -2 ], [ 5, -5, -2, 0, -2, -2 ], [ 5, -5, -2, 0, 0, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], - [ [ 7, -5, -3, 0, -1, -2 ], [ 5, -5, -2, 0, -2, -2 ], [ 6, -5, -4, 0, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], - [ [ 8, -6, -4, 0, -1, -2 ], [ 5, -5, -2, 0, -2, -2 ], [ 6, -5, -4, 0, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], - [ [ 8, -6, -4, 0, -1, -2 ], [ 6, -5, -4, 0, -1, -3 ], [ 6, -5, -4, 0, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ], - [ [ 8, -6, -4, 0, -1, -2 ], [ 6, -5, -4, 0, -1, -3 ], [ 7, -7, -4, 0, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ] ] -], -"cur_uid": "703e109b", -"ref_uid": "tmp", -"order_seed": 550421, -"dur_seed": 315472, -"motifs_seed": 675194, -"entrances_probs_vals": [ 0.52, 0.56, 2.4206349206349, 0.25, 1.24, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"passages_probs_vals": [ 0.52, 0.56, 2.4206349206349, 0.25, 1.24, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0.52, 0.56, 2.4206349206349, 0.25, 1.24, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ 1211.1455108359, 2400 ], [ -1650, 450 ], [ -405, 1137 ], [ 951.08359133127, 2053 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 3, 0 ], [ 2 ], [ 1 ] ] -], -"sus_weights": [ 0.73, 0.49, 0 ], -"order_size": [ 1, 3 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/74faf83f/74faf83f_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/74faf83f/74faf83f_code.scd deleted file mode 100644 index 3ec9b1a..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/74faf83f/74faf83f_code.scd +++ /dev/null @@ -1,907 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1, 3)}, {rrand(0.3, 0.5)}); - }); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - ledger = ledger.drop(-1).add(curUID); - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, attack, release = 1, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = rrand(20, 40); - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - //sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * amp * EnvGen.kr(Env.adsr(attack, 0.3, 0.9, release, 0.9, -3), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); - //Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.sine(dur), gate, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs, hierarchicalDust; - - hierarchicalDust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) - ); - - sigs = [~stringModelBusArray, ~sineBusArray, ~bassBusArray, ~hdustBusArray, ~samplerBusArray].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -mixer = Synth.tail(~group, \mixer); -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/74faf83f/74faf83f_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/74faf83f/74faf83f_mus_model.json deleted file mode 100644 index 38b642a..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/74faf83f/74faf83f_mus_model.json +++ /dev/null @@ -1,83 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 0, 2, 0, 1, -2, 0 ], [ "Rest" ] ], 1.625 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 2, 0, 1, -2, 0 ], [ 0, 2, 0, 2, -2, -1 ] ], 1.625 ], - [ [ [ -3, 2, 0, 2, -2, -2 ], [ "Rest" ], [ 0, 2, 0, 1, -2, 0 ], [ 0, 2, 0, 2, -2, -1 ] ], 2.75 ] - ], - [ - [ [ [ -3, 2, 0, 2, -2, -2 ], [ "Rest" ], [ 0, 2, 0, 1, -2, 0 ], [ "Rest" ] ], 0.75 ], - [ [ [ -3, 2, 0, 2, -2, -2 ], [ -2, 3, 0, 1, -2, -1 ], [ 0, 2, 0, 1, -2, 0 ], [ "Rest" ] ], 2.75 ], - [ [ [ -3, 3, 0, 1, -3, -1 ], [ -2, 3, 0, 1, -2, -1 ], [ 0, 2, 0, 1, -2, 0 ], [ "Rest" ] ], 1.25 ], - [ [ [ -3, 3, 0, 1, -3, -1 ], [ -2, 3, 0, 1, -2, -1 ], [ 1, 3, 0, 0, -2, -1 ], [ "Rest" ] ], 2.5 ] - ], - [ - [ [ [ -3, 3, 0, 1, -3, -1 ], [ -2, 3, 0, 1, -2, -1 ], [ "Rest" ], [ "Rest" ] ], 0.75 ], - [ [ [ -3, 3, 0, 1, -3, -1 ], [ -2, 3, 0, 1, -2, -1 ], [ "Rest" ], [ 0, 2, 0, 2, -2, -1 ] ], 3.25 ], - [ [ [ -3, 3, 0, 1, -3, -1 ], [ -2, 2, -1, 2, -2, -1 ], [ "Rest" ], [ 0, 2, 0, 2, -2, -1 ] ], 0.75 ], - [ [ [ -3, 1, 0, 2, -2, -1 ], [ -2, 2, -1, 2, -2, -1 ], [ "Rest" ], [ 0, 2, 0, 2, -2, -1 ] ], 1.625 ], - [ [ [ -3, 1, 0, 2, -2, -1 ], [ -3, 3, 0, 2, -2, -1 ], [ "Rest" ], [ 0, 2, 0, 2, -2, -1 ] ], 1 ], - [ [ [ -3, 1, 0, 2, -2, -1 ], [ -2, 1, 0, 2, -2, -1 ], [ "Rest" ], [ 0, 2, 0, 2, -2, -1 ] ], 1.25 ], - [ [ [ -3, 2, 0, 1, -2, -1 ], [ -2, 1, 0, 2, -2, -1 ], [ "Rest" ], [ 0, 2, 0, 2, -2, -1 ] ], 0.875 ], - [ [ [ -3, 2, 0, 2, -2, -2 ], [ -2, 1, 0, 2, -2, -1 ], [ "Rest" ], [ 0, 2, 0, 2, -2, -1 ] ], 1.625 ] - ], - [ - [ [ [ "Rest" ], [ -2, 1, 0, 2, -2, -1 ], [ "Rest" ], [ 0, 2, 0, 2, -2, -1 ] ], 0.75 ], - [ [ [ "Rest" ], [ -2, 1, 0, 2, -2, -1 ], [ 1, 3, 0, 0, -2, -1 ], [ 0, 2, 0, 2, -2, -1 ] ], 2.625 ], - [ [ [ "Rest" ], [ -2, 4, 0, 0, -2, -1 ], [ 1, 3, 0, 0, -2, -1 ], [ 0, 2, 0, 2, -2, -1 ] ], 0.75 ], - [ [ [ "Rest" ], [ -2, 4, 0, 0, -2, -1 ], [ 1, 3, 0, 0, -2, -1 ], [ 0, 3, 0, 1, -2, -1 ] ], 0.875 ], - [ [ [ "Rest" ], [ -2, 4, 0, 0, -2, -1 ], [ 1, 3, 0, 0, -2, -1 ], [ 0, 3, 0, 0, -2, 0 ] ], 2.375 ] - ], - [ - [ [ [ "Rest" ], [ "Rest" ], [ 1, 3, 0, 0, -2, -1 ], [ 0, 3, 0, 0, -2, 0 ] ], 1.625 ], - [ [ [ -3, 2, 0, 2, -2, -2 ], [ "Rest" ], [ 1, 3, 0, 0, -2, -1 ], [ 0, 3, 0, 0, -2, 0 ] ], 2.5 ], - [ [ [ -3, 2, 0, 2, -2, -2 ], [ "Rest" ], [ 0, 3, 0, 2, -2, -2 ], [ 0, 3, 0, 0, -2, 0 ] ], 1.25 ], - [ [ [ -3, 2, 0, 2, -2, -2 ], [ "Rest" ], [ 0, 3, 0, 2, -2, -2 ], [ 0, 2, 0, 2, -1, -2 ] ], 2.75 ] - ], - [ - [ [ [ -3, 2, 0, 2, -2, -2 ], [ -2, 4, 0, 0, -2, -1 ], [ 0, 3, 0, 2, -2, -2 ], [ 0, 2, 0, 2, -1, -2 ] ], 1.75 ], - [ [ [ -3, 2, 0, 2, -2, -2 ], [ -2, 4, 0, 0, -2, -1 ], [ 0, 4, 1, 0, -2, -1 ], [ 0, 2, 0, 2, -1, -2 ] ], 1.25 ], - [ [ [ -3, 2, 0, 2, -2, -2 ], [ -2, 4, 0, 0, -2, -1 ], [ 0, 4, 1, 0, -2, -1 ], [ 1, 4, 0, 0, -2, -2 ] ], 1.625 ], - [ [ [ -4, 4, 0, 1, -2, -1 ], [ -2, 4, 0, 0, -2, -1 ], [ 0, 4, 1, 0, -2, -1 ], [ 1, 4, 0, 0, -2, -2 ] ], 2.125 ], - [ [ [ "Rest" ], [ -2, 4, 0, 0, -2, -1 ], [ 0, 4, 1, 0, -2, -1 ], [ 1, 4, 0, 0, -2, -2 ] ], 1.375 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 4, 1, 0, -2, -1 ], [ 1, 4, 0, 0, -2, -2 ] ], 1 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 1, 4, 0, 0, -2, -2 ] ], 0.875 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3 ] - ] - ] -], -"last_changes": -[ - [ [ -3, 2, 0, 2, -2, -2 ], [ -2, 4, 0, 0, -2, -1 ], [ 0, 3, 0, 2, -2, -2 ], [ 0, 3, 0, 0, -2, 0 ] ], - [ [ -3, 2, 0, 2, -2, -2 ], [ -2, 4, 0, 0, -2, -1 ], [ 0, 3, 0, 2, -2, -2 ], [ 0, 2, 0, 2, -1, -2 ] ], - [ [ -3, 2, 0, 2, -2, -2 ], [ -2, 4, 0, 0, -2, -1 ], [ 0, 4, 1, 0, -2, -1 ], [ 0, 2, 0, 2, -1, -2 ] ], - [ [ -3, 2, 0, 2, -2, -2 ], [ -2, 4, 0, 0, -2, -1 ], [ 0, 4, 1, 0, -2, -1 ], [ 1, 4, 0, 0, -2, -2 ] ], - [ [ -4, 4, 0, 1, -2, -1 ], [ -2, 4, 0, 0, -2, -1 ], [ 0, 4, 1, 0, -2, -1 ], [ 1, 4, 0, 0, -2, -2 ] ] -], -"cur_uid": "74faf83f", -"ref_uid": "tmp", -"order_seed": 329828, -"dur_seed": 441173, -"motifs_seed": 330575, -"entrances_probs_vals": [ 0, 0.48, 1.7460317460317, 0.58, 1.68, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"passages_probs_vals": [ 0, 0.48, 1.7460317460317, 0.58, 1.68, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0, 0.48, 1.7460317460317, 0.58, 1.68, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ -3600, -1408.0495356037 ], [ -3600, -609.2879256966 ], [ 858.20433436532, 2066 ], [ 951.08359133127, 2053 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 2, 3 ], [ 0 ], [ 1 ] ], - [ [ 1 ], [ 0, 2 ], [ 3 ] ], - [ [ 3 ], [ 1, 0, 1, 1, 0, 0 ], [ 2 ] ], - [ [ 2 ], [ 1, 3, 3 ], [ 0 ] ], - [ [ 0 ], [ 2, 3 ], [ 1 ] ], - [ [ 1 ], [ 2, 3, 0 ], [ ] ] -], -"sus_weights": [ 0.73, 0.49, 0 ], -"order_size": [ 1, 7 ], -"passages_size": [ 0, 5 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/7ac10d34/7ac10d34_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/7ac10d34/7ac10d34_code.scd deleted file mode 100644 index 65c17df..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/7ac10d34/7ac10d34_code.scd +++ /dev/null @@ -1,719 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON; - -// model vars -//(model and global vars mostly set by OSC funcs -var curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, orders, susWeights, passagesWeights, passagesSize, orderSize; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var lastXChanges, popSize, exPath, dir, primes, dims, tuples, -seq, group, player, ledgerPath, ledger, currentlyPlayingUID; - - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, min, max, envData; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - durFunc = {arg allowChord; - var res; - res = if(allowChord.not, { - pTable.tableRand * (max - min) + min - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (max - min) + min}); - }).round(0.125); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, durSeed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - allowChord = if((sus ++ silent).includes(ins), { - (sus ++ silent).includes(ins) && (ins != sus.last); - }, { - if(i < (flatOrder.size - 1), {(isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not}, {false}); - }); - dur = passagesDurFunc.value(allowChord); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(isLastOrder, { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - dur = passagesDurFunc.value(allowChord); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); - -genPatterns = {arg inSeq, addr; - var voices, durs, patterns, res, indices, sectionDurs, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - indices = inSeq.collect({arg mSeq, m; mSeq[1]}); - ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - res = Ppar( - voices.flop.collect({arg voice; - var clumps, hdScores, freqs, fDurs; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \instrument, \test, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1) - ) - }) ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \indexPath, "/cur_play_index", - \indexMsg, Pseq(indices.postln, 1), - \seqPath, "/mus_seq", - \seqMsg, Pseq(seq, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - ); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < (maxDepth - 0), { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path; - var file, nameSpaces, modelItems, resString; - file = File(path,"w"); - - nameSpaces = [ - "music_data", "last_changes", - "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size" - ]; - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize - ]; - - resString = [nameSpaces, modelItems].flop.collect({arg item; - var nameSpace, modelItem, depth = 0, insert = " "; - # nameSpace, modelItem = item; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(modelItem.postln, depth).postln - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg model; - var nameSpaces, data; - - //model = File(path, "r").readAllString.parseJSON; - - nameSpaces = [ - "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size" - ]; - - data = nameSpaces.collect({arg nS; msgInterpret.value(model[nS]).postln}); - - data.postln; - - # curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize = data; - - popSize = ranges.size; -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg ledger; ledger = ledger["ledger"]}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - loadModelFile.value(msg[1].asString); -}, \load_model); - - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dFormat, condition, musPath; - msg.postln; - - path = msg[1].asString; - - loadModelFile.value(path); - - refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - lastXChanges = if(refUID == nil, { - [initVoices.value().deepCopy]; - }, { - var file; - refUID.postln; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..2] ++ [entrancesProbVals[3..]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..2] ++ [passagesProbVals[3..]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..2] ++ [exitsProbVals[3..]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - //musPath = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - writeResources.value(path); - - //orders = nil; - //addr.sendMsg("/current_uid", curUID); - //addr.sendMsg("/ledger", prettifyArray.value(ledger, 1).replace("\"", "")); - //addr.sendMsg("/ledger_size", ledger.size); - //addr.sendMsg("/mus_seq", prettifyArray.value(seq, 3)); - addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var newLedger, modelPath, musString, musFile, test1, test2; - msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - curUID = genUID.value; - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - writeResources.value(modelPath); - - File.delete(ledgerPath.postln ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - newLedger = File(ledgerPath.postln, "w"); - ledger = ledger.postln.drop(-1).add(curUID); - newLedger.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - newLedger.close; - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - player.stop; - group.set(\gate, 0); - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var file; - (indexStart + index).postln; - file = File((dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_music" ++ ".json").standardizePath, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, {pSeq = pSeq.add([seq, ledger.size - 1])}); - patterns = genPatterns.value(pSeq, addr); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms; - noHarms = 30; - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) - -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) - - - -"{\"a\": 1}".parseYAML["a"].asInteger; -"{\"a\": 1}".parseJSON["a"].isNumber; - -1223423434123.asHexString.toLower - -Date.getDate.rawSeconds -Date.seed.asHexString.toLower - -n = NetAddr("localhost", 8080); -n.sendMsg("/GET/#", (NetAddr.localAddr.hostname ++ ":" ++ NetAddr.localAddr.port), "/passage_probs_vals"); \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/7ac10d34/7ac10d34_gui_state.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/7ac10d34/7ac10d34_gui_state.json deleted file mode 100644 index 84e6edd..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/7ac10d34/7ac10d34_gui_state.json +++ /dev/null @@ -1,1359 +0,0 @@ -{ - "motif_label": "motif", - "seeds_label": "seeds", - "order": "[\n [ [ 3, 1, 0 ], [ 2 ], [ ] ],\n [ [ 1, 2 ], [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 3 ] ],\n [ [ 3, 2 ], [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ], [ 0 ] ],\n [ [ 2, 3 ], [ 0, 1, 0 ], [ ] ]\n]", - "order_lock": 1, - "order_size": [ - 3, - 8 - ], - "order_size_v2": 8, - "order_size_v1": 3, - "order_size_panel": -1, - "passage_size_v2": 8, - "passage_size_v1": 2, - "passage_size_panel": -1, - "sus_weights": [ - null, - null, - null - ], - "range_matrix": [ - null, - null, - null, - null - ], - "instrumentation": [ - 0, - 0 - ], - "entrances_probs_sync": "passages", - "entrances": -1, - "passages_probs_sync": "passages", - "passages": -1, - "exits_probs_sync": "passages", - "exits": -1, - "dur_panel": 0, - "durations": -1, - "passages_weights": [ - null, - null, - null, - null, - null - ], - "weights": -1, - "seeds_tab_panel": 0, - "weights_seed_lock": 0, - "weights_seed": 534103, - "sus_weights/0_slider_val": 0.21, - "sus_weights/0_slider_slider": 0.21, - "sus_weights/0_slider_input": 0.21, - "sus_weights/0_slider_label": 1, - "sus_weights/0_slider": -1, - "sus_weights/1_slider_val": 0.35, - "sus_weights/1_slider_slider": 0.35, - "sus_weights/1_slider_input": 0.35, - "sus_weights/1_slider_label": 2, - "sus_weights/1_slider": -1, - "sus_weights/2_slider_val": 0.21, - "sus_weights/2_slider_slider": 0.21, - "sus_weights/2_slider_input": 0.21, - "sus_weights/2_slider_label": 3, - "sus_weights/2_slider": -1, - "passages_weights/0_slider_val": 0.49, - "passages_weights/0_slider_slider": 0.49, - "passages_weights/0_slider_input": 0.49, - "passages_weights/0_slider_label": "step", - "passages_weights/0_slider": -1, - "passages_weights/1_slider_val": 0.53, - "passages_weights/1_slider_slider": 0.53, - "passages_weights/1_slider_input": 0.53, - "passages_weights/1_slider_label": "dc", - "passages_weights/1_slider": -1, - "passages_weights/2_slider_val": 0.35, - "passages_weights/2_slider_slider": 0.35, - "passages_weights/2_slider_input": 0.35, - "passages_weights/2_slider_label": "range", - "passages_weights/2_slider": -1, - "passages_weights/3_slider_val": 0.59, - "passages_weights/3_slider_slider": 0.59, - "passages_weights/3_slider_input": 0.59, - "passages_weights/3_slider_label": "registration", - "passages_weights/3_slider": -1, - "passages_weights/4_slider_val": 0.39, - "passages_weights/4_slider_slider": 0.39, - "passages_weights/4_slider_input": 0.39, - "passages_weights/4_slider_label": "hd", - "passages_weights/4_slider": -1, - "range_matrix/0_val_input_min": -853.2067988668555, - "range_matrix/0_val_rslider": [ - -853.2067988668555, - 401 - ], - "range_matrix/0_val_input_max": 401, - "range_matrix/0_val": -1, - "range_matrix/1_val_input_min": -659, - "range_matrix/1_val_rslider": [ - -659, - 880 - ], - "range_matrix/1_val_input_max": 880, - "range_matrix/1_val": -1, - "range_matrix/2_val_input_min": -241, - "range_matrix/2_val_rslider": [ - -241, - 1869 - ], - "range_matrix/2_val_input_max": 1869, - "range_matrix/2_val": -1, - "range_matrix/3_val_input_min": -27, - "range_matrix/3_val_rslider": [ - -27, - 2063 - ], - "range_matrix/3_val_input_max": 2063, - "range_matrix/3_val": -1, - "entrances_probs_chord_slider_val": 0.66, - "entrances_probs_chord_slider_slider": 0.66, - "entrances_probs_chord_slider_input": 0.66, - "entrances_probs_chord_slider_label": "chord prob", - "entrances_probs_chord_slider": -1, - "entrances_probs_vals": [ - 0.63, - 0, - 5, - 0, - 0.5, - 0.23316062176165803, - 0.7094594594594594, - 0.3963730569948187, - 0.8716216216216216, - 0.4948186528497409, - 0.5912162162162162, - 0.5362694300518135, - 0.8614864864864865, - 0.6424870466321243, - 0.5912162162162162, - 0.7901554404145078, - 0.8277027027027027, - 1, - 0.5 - ], - "entrances_probs": -1, - "passages_probs_chord_slider_val": 0.63, - "passages_probs_chord_slider_slider": 0.63, - "passages_probs_chord_slider_input": 0.63, - "passages_probs_chord_slider_label": "chord prob", - "passages_probs_chord_slider": -1, - "passages_probs_vals": [ - 0.63, - 0, - 5, - 0, - 0.5, - 0.23316062176165803, - 0.7094594594594594, - 0.3963730569948187, - 0.8716216216216216, - 0.4948186528497409, - 0.5912162162162162, - 0.5362694300518135, - 0.8614864864864865, - 0.6424870466321243, - 0.5912162162162162, - 0.7901554404145078, - 0.8277027027027027, - 1, - 0.5 - ], - "passages_probs": -1, - "exits_probs_chord_slider_val": 0, - "exits_probs_chord_slider_slider": 0, - "exits_probs_chord_slider_input": 0, - "exits_probs_chord_slider_label": "chord prob", - "exits_probs_chord_slider": -1, - "exits_probs_vals": [ - 0, - 0, - 5, - 0, - 0.5, - 0.23316062176165803, - 0.7094594594594594, - 0.4948186528497409, - 0.5912162162162162, - 0.7901554404145078, - 0.8277027027027027, - 1, - 0.5 - ], - "exits_probs": -1, - "step_env_env_vals": [ - 0, - 5, - 0, - 0, - 0, - 0, - 0.14609053497942387, - 0.7613636363636364, - 0.20164609053497942, - 0.26136363636363635, - 0.24279835390946503, - 0.7215909090909092, - 0.39094650205761317, - 0.875, - 0.4567901234567901, - 0.44318181818181823, - 0.5432098765432098, - 0.34659090909090906, - 0.6481481481481481, - 0.8011363636363636, - 0.6810699588477366, - 0.5170454545454546, - 0.8868312757201646, - 0.49431818181818177, - 0.8868312757201646, - 0.49431818181818177 - ], - "step_env_env_canvas": [ - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 0.14609053497942387, - 0.7613636363636364 - ], - [ - 0.20164609053497942, - 0.26136363636363635 - ], - [ - 0.24279835390946503, - 0.7215909090909092 - ], - [ - 0.39094650205761317, - 0.875 - ], - [ - 0.4567901234567901, - 0.44318181818181823 - ], - [ - 0.5432098765432098, - 0.34659090909090906 - ], - [ - 0.6481481481481481, - 0.8011363636363636 - ], - [ - 0.6810699588477366, - 0.5170454545454546 - ], - [ - 0.8868312757201646, - 0.49431818181818177 - ], - [ - 0.8868312757201646, - 0.49431818181818177 - ], - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - "step_env_env_size": 12, - "step_env_env_flatten": 0, - "step_env_env_rslider": [ - 0, - 5 - ], - "step_env_env_rslider_v2": 5, - "step_env_env_rslider_v1": 0, - "step_env_env_mpos": "", - "step_env_env": -1, - "entrances_probs_dur_env_vals": [ - 0.515267175572519, - 4.599236641221374, - 0, - 0.5, - 0.2772020725388601, - 0.7972972972972973, - 0.45077720207253885, - 0.8783783783783784, - 0.5, - 0.5, - 0.727979274611399, - 0.45270270270270274, - 0.7357512953367875, - 0.6486486486486487, - 0.8911917098445595, - 0.7905405405405406, - 1, - 0.5 - ], - "entrances_probs_dur_env_canvas": [ - [ - 0, - 0.5 - ], - [ - 0.2772020725388601, - 0.7972972972972973 - ], - [ - 0.45077720207253885, - 0.8783783783783784 - ], - [ - 0.5, - 0.5 - ], - [ - 0.727979274611399, - 0.45270270270270274 - ], - [ - 0.7357512953367875, - 0.6486486486486487 - ], - [ - 0.8911917098445595, - 0.7905405405405406 - ], - [ - 1, - 0.5 - ], - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - "entrances_probs_dur_env_size": 8, - "entrances_probs_dur_env_flatten": 0, - "entrances_probs_dur_env_rslider": [ - 0.515267175572519, - 4.599236641221374 - ], - "entrances_probs_dur_env_rslider_v2": 4.599236641221374, - "entrances_probs_dur_env_rslider_v1": 0.515267175572519, - "entrances_probs_dur_env_mpos": "", - "entrances_probs_dur_env": -1, - "passages_probs_dur_env_vals": [ - 0, - 5, - 0, - 0.5, - 0.23316062176165803, - 0.7094594594594594, - 0.3963730569948187, - 0.8716216216216216, - 0.4948186528497409, - 0.5912162162162162, - 0.5362694300518135, - 0.8614864864864865, - 0.6424870466321243, - 0.5912162162162162, - 0.7901554404145078, - 0.8277027027027027, - 1, - 0.5 - ], - "passages_probs_dur_env_canvas": [ - [ - 0, - 0.5 - ], - [ - 0.23316062176165803, - 0.7094594594594594 - ], - [ - 0.3963730569948187, - 0.8716216216216216 - ], - [ - 0.4948186528497409, - 0.5912162162162162 - ], - [ - 0.5362694300518135, - 0.8614864864864865 - ], - [ - 0.6424870466321243, - 0.5912162162162162 - ], - [ - 0.7901554404145078, - 0.8277027027027027 - ], - [ - 1, - 0.5 - ], - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - "passages_probs_dur_env_size": 8, - "passages_probs_dur_env_flatten": 0, - "passages_probs_dur_env_rslider": [ - 0, - 5 - ], - "passages_probs_dur_env_rslider_v2": 5, - "passages_probs_dur_env_rslider_v1": 0, - "passages_probs_dur_env_mpos": "", - "passages_probs_dur_env": -1, - "exits_probs_dur_env_vals": [ - 0, - 5, - 0, - 0.5, - 0.5, - 0.5, - 1, - 0.5 - ], - "exits_probs_dur_env_canvas": [ - [ - 0, - 0.5 - ], - [ - 0.5, - 0.5 - ], - [ - 1, - 0.5 - ], - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - "exits_probs_dur_env_size": 3, - "exits_probs_dur_env_flatten": 0, - "exits_probs_dur_env_rslider": [ - 0, - 5 - ], - "exits_probs_dur_env_rslider_v2": 5, - "exits_probs_dur_env_rslider_v1": 0, - "exits_probs_dur_env_mpos": "", - "exits_probs_dur_env": -1, - "mus_seq": [ - [ - [ - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - "Rest" - ], - [ - "Rest" - ] - ], - 0 - ], - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -3, - 0, - 1, - -1 - ], - [ - "Rest" - ] - ], - 1.75 - ], - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 1.75 - ], - [ - [ - [ - 0, - 1, - -3, - 0, - 2, - -1 - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 0.75 - ], - [ - [ - [ - 1, - 1, - -2, - -2, - 1, - 0 - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 0.625 - ], - [ - [ - [ - 1, - 1, - -3, - -1, - 0, - 0 - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 0.625 - ], - [ - [ - [ - 1, - 0, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 1.75 - ] - ], - [ - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 0 - ], - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -3, - -1, - 1, - 0 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 1.75 - ], - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 0, - 1, - -2, - 0, - 1, - 0 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 1.375 - ], - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 0, - 2, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 0.75 - ], - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 0, - 1, - -2, - -1, - 2, - 0 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 1.75 - ], - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 0, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 1.875 - ], - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -2, - -1, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 1 - ] - ], - [ - [ - [ - [ - 1, - 0, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -2, - -1, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 0 - ], - [ - [ - [ - 1, - 0, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 2, - 0, - -3, - -1, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 1.625 - ], - [ - [ - [ - 1, - 0, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 0, - 1, - -1, - -1, - 1, - 0 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 1.75 - ], - [ - [ - [ - 1, - 0, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 0, - 1, - -1, - -1, - 1, - 0 - ], - [ - "Rest" - ] - ], - 0 - ], - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 0, - 1, - -1, - -1, - 1, - 0 - ], - [ - "Rest" - ] - ], - 1.875 - ], - [ - [ - [ - "Rest" - ], - [ - "Rest" - ], - [ - 0, - 1, - -1, - -1, - 1, - 0 - ], - [ - "Rest" - ] - ], - 0 - ], - [ - [ - [ - "Rest" - ], - [ - "Rest" - ], - [ - "Rest" - ], - [ - "Rest" - ] - ], - 0.875 - ] - ] - ] - ], - "root": [ - 0.20743639921722112, - 0 - ], - "order_seed": 798574, - "dur_seed": 884869, - "passages_size": [ - 0, - 10 - ], - "dur_seed_lock": 1, - "order_seed_lock": 0, - "seeds_panel": -1, - "motif_panel": [ - 0, - 0 - ], - "ref_uid": "6f1a789f", - "cur_uid": "7ac10d34" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/7ac10d34/7ac10d34_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/7ac10d34/7ac10d34_mus_model.json deleted file mode 100644 index 73f197b..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/7ac10d34/7ac10d34_mus_model.json +++ /dev/null @@ -1,59 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.375 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 1 ], [ "Rest" ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 1, 0, 0, 0, 0 ], [ "Rest" ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 1, 0 ], [ "Rest" ] ], 0.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, -1, 0 ], [ "Rest" ] ], 1.5 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ] ], 1.125 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 1, 0, 0, 0 ], [ "Rest" ] ], 1.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, -1, 0, 0 ], [ "Rest" ] ], 1.625 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ "Rest" ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.25 ], - [ [ [ 1, -1, 1, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.125 ], - [ [ [ 2, -2, 0, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 1, 0, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 0.5 ], - [ [ [ 1, 0, -1, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.625 ], - [ [ [ 2, -1, 0, -1, 0, -1 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 2 ], - [ [ [ 2, -1, 0, -2, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.75 ], - [ [ [ 1, -1, 1, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.5 ], - [ [ [ 2, -2, 0, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.25 ], - [ [ [ 2, -2, 0, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ "Rest" ] ], 0.875 ], - [ [ [ 2, -2, 0, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ 2, -2, 0, -1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.375 ] - ] - ] -], -"last_changes": -[ - [ [ 1, 0, -1, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], - [ [ 2, -1, 0, -1, 0, -1 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], - [ [ 2, -1, 0, -2, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], - [ [ 1, -1, 1, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], - [ [ 2, -2, 0, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ] -], -"cur_uid": "7ac10d34", -"ref_uid": "46b6952a", -"order_seed": 638872, -"dur_seed": 225879, -"motifs_seed": 992393, -"entrances_probs_vals": [ 0.75, 0.5, 2, 0, 0.5, 0.26424870466321, 0.75675675675676, 0.5, 0.5, 0.58549222797927, 0.72635135135135, 1, 0.5 ], -"passages_probs_vals": [ 0.75, 0.5, 2, 0, 0.5, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0.75, 0.5, 2, 0, 0.5, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ -384, 2400 ], [ -507, 2400 ], [ -282, 2237 ], [ -1200, 2053 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 0 ], [ 2, 2, 2, 2, 2, 2, 2 ], [ 3, 1 ] ], - [ [ 1, 2, 3 ], [ 0, 0, 0, 0, 0, 0, 0, 0 ], [ ] ] -], -"sus_weights": [ 0.75, 0.69, 0.75 ], -"order_size": [ 2, 6 ], -"passages_size": [ 0, 10 ] -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/7bf874ce/7bf874ce_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/7bf874ce/7bf874ce_code.scd deleted file mode 100644 index ab370bd..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/7bf874ce/7bf874ce_code.scd +++ /dev/null @@ -1,887 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - lastXChanges = if(refUID == nil, { - [initVoices.value().deepCopy]; - }, { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - ledger = ledger.drop(-1).add(curUID); - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - player.stop; - group.set(\gate, 0); - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = 30; - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs, hierarchicalDust; - - hierarchicalDust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) - ); - - sigs = [~stringModelBusArray, ~sineBusArray, ~bassBusArray, ~hdustBusArray, ~samplerBusArray].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -mixer = Synth.tail(~group, \mixer); -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/7bf874ce/7bf874ce_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/7bf874ce/7bf874ce_mus_model.json deleted file mode 100644 index 4675781..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/7bf874ce/7bf874ce_mus_model.json +++ /dev/null @@ -1,59 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ], [ "Rest" ] ], 0.375 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ], [ "Rest" ] ], 2.25 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 1, 0, 0, 0 ] ], 0.375 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 1, 0, 0, 0 ] ], 0.5 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 2, 0, 0, 0, 0, -1 ] ], 0.375 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 2, 0, 0, 0, 0, -1 ] ], 3.625 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ], [ 2, 0, 0, 0, 0, -1 ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ], [ "Rest" ] ], 0.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 1, 0, 0 ], [ "Rest" ] ], 0.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 4.125 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0.375 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ], [ "Rest" ] ], 0.5 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ], [ 1, 0, 1, 0, 0, 0 ] ], 4 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 1, 1, 0, 0, 0 ], [ 1, 0, 1, 0, 0, 0 ] ], 0.5 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, 1, 0, 0, 0 ], [ 1, 0, 1, 0, 0, 0 ] ], 0.875 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, 1, 0, 0, 0 ], [ "Rest" ] ], 0.5 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 4.375 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 2, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 2, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 2, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ], [ 2, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ], [ 1, 0, 1, 0, 0, 0 ] ] -], -"cur_uid": "7bf874ce", -"ref_uid": "6d0c2f19", -"order_seed": 460016, -"dur_seed": 553757, -"motifs_seed": 771464, -"entrances_probs_vals": [ 0, 1.67, 4.8015873015873, 0.24725274725275, 1.15, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"passages_probs_vals": [ 0, 1.67, 4.8015873015873, 0.24725274725275, 1.15, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0, 1.67, 4.8015873015873, 0.24725274725275, 1.15, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ -1100, 460.68111455108 ], [ -507, 1084.8297213622 ], [ 884.21052631579, 2237 ], [ 1040.2476780186, 2053 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 2, 0 ], [ 3, 1, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 2 ], [ 1, 3 ] ], - [ [ 1, 0 ], [ 2, 3 ], [ ] ] -], -"sus_weights": [ 0.75, 0.69, 0.75 ], -"order_size": [ 1, 4 ], -"passages_size": [ 0, 3 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/7c7a96a2/7c7a96a2_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/7c7a96a2/7c7a96a2_code.scd deleted file mode 100644 index 1b308bc..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/7c7a96a2/7c7a96a2_code.scd +++ /dev/null @@ -1,897 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, rels; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - rels = freqs.drop(-1).collect({rrand(0.3, 0.5)}) ++ [rrand(1, 2)]; - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - ledger = ledger.drop(-1).add(curUID); - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - player.stop; - group.set(\gate, 0); - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = 30; - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 3, 0.9), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); - //Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.sine(dur), gate, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs, hierarchicalDust; - - hierarchicalDust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) - ); - - sigs = [~stringModelBusArray, ~sineBusArray, ~bassBusArray, ~hdustBusArray, ~samplerBusArray].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -mixer = Synth.tail(~group, \mixer); -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/7c7a96a2/7c7a96a2_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/7c7a96a2/7c7a96a2_mus_model.json deleted file mode 100644 index cd8ded8..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/7c7a96a2/7c7a96a2_mus_model.json +++ /dev/null @@ -1,45 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ 1, 0, 0, -1, 1, -1 ], [ "Rest" ], [ "Rest" ] ], 1.625 ], - [ [ [ "Rest" ], [ 1, 0, 0, -1, 1, -1 ], [ "Rest" ], [ 3, 0, 0, -1, 0, -1 ] ], 1.25 ], - [ [ [ 0, 1, 0, -1, 1, -1 ], [ 1, 0, 0, -1, 1, -1 ], [ "Rest" ], [ 3, 0, 0, -1, 0, -1 ] ], 1.25 ], - [ [ [ 0, 1, 0, -1, 1, -1 ], [ 1, 0, 0, -1, 1, -1 ], [ 3, 0, -1, -1, 1, -1 ], [ 3, 0, 0, -1, 0, -1 ] ], 1.5 ], - [ [ [ 0, 0, 0, -1, 2, -1 ], [ 1, 0, 0, -1, 1, -1 ], [ 3, 0, -1, -1, 1, -1 ], [ 3, 0, 0, -1, 0, -1 ] ], 2.125 ], - [ [ [ 0, 0, 0, -1, 2, -1 ], [ 1, 0, 0, -1, 1, -1 ], [ "Rest" ], [ 3, 0, 0, -1, 0, -1 ] ], 1.5 ], - [ [ [ 0, 0, 0, -1, 2, -1 ], [ "Rest" ], [ "Rest" ], [ 3, 0, 0, -1, 0, -1 ] ], 1.125 ], - [ [ [ 0, 0, 0, -1, 2, -1 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.375 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.75 ] - ] - ] -], -"last_changes": -[ - [ [ -1, 0, 0, 1, 1, -1 ], [ 1, 0, 0, -1, 1, -1 ], [ 2, 0, 0, 0, 1, -1 ], [ 1, 1, 0, 0, 1, -1 ] ], - [ [ -1, 0, 0, 1, 1, -1 ], [ 1, 0, 0, -1, 1, -1 ], [ 2, 0, 0, 0, 1, -1 ], [ 3, 0, 0, -1, 0, -1 ] ], - [ [ 0, 1, 0, -1, 1, -1 ], [ 1, 0, 0, -1, 1, -1 ], [ 2, 0, 0, 0, 1, -1 ], [ 3, 0, 0, -1, 0, -1 ] ], - [ [ 0, 1, 0, -1, 1, -1 ], [ 1, 0, 0, -1, 1, -1 ], [ 3, 0, -1, -1, 1, -1 ], [ 3, 0, 0, -1, 0, -1 ] ], - [ [ 0, 0, 0, -1, 2, -1 ], [ 1, 0, 0, -1, 1, -1 ], [ 3, 0, -1, -1, 1, -1 ], [ 3, 0, 0, -1, 0, -1 ] ] -], -"cur_uid": "7c7a96a2", -"ref_uid": "6f1305ed", -"order_seed": 768571, -"dur_seed": 647965, -"motifs_seed": 710750, -"entrances_probs_vals": [ 0, 0.48, 1.7460317460317, 0.58, 1.6758241758242, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"passages_probs_vals": [ 0, 0.48, 1.7460317460317, 0.58, 1.6758241758242, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0, 0.48, 1.7460317460317, 0.58, 1.6758241758242, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ -1100, 237.77089783282 ], [ -1066.253869969, 260.06191950464 ], [ 1207.4303405573, 2065.6346749226 ], [ 1040.2476780186, 2053 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 1 ], [ 3, 0, 2, 0 ], [ ] ] -], -"sus_weights": [ 0.73, 0.49, 0 ], -"order_size": [ 1, 7 ], -"passages_size": [ 0, 2 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/7c8bc6df/7c8bc6df_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/7c8bc6df/7c8bc6df_code.scd deleted file mode 100644 index a4e8b56..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/7c8bc6df/7c8bc6df_code.scd +++ /dev/null @@ -1,907 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1, 3)}, {rrand(0.3, 0.5)}); - }); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - ledger = ledger.drop(-1).add(curUID); - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, attack, release = 1, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = 30; - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * amp * EnvGen.kr(Env.adsr(attack, 0.3, 0.9, release, 0.9, -3), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); - //Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.sine(dur), gate, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs, hierarchicalDust; - - hierarchicalDust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) - ); - - sigs = [~stringModelBusArray, ~sineBusArray, ~bassBusArray, ~hdustBusArray, ~samplerBusArray].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -mixer = Synth.tail(~group, \mixer); -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/7c8bc6df/7c8bc6df_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/7c8bc6df/7c8bc6df_mus_model.json deleted file mode 100644 index a8f0de5..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/7c8bc6df/7c8bc6df_mus_model.json +++ /dev/null @@ -1,84 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 6, -1, 0, -1, -1, -4 ], [ "Rest" ] ], 2.375 ], - [ [ [ "Rest" ], [ 4, -1, 1, -1, -1, -4 ], [ 6, -1, 0, -1, -1, -4 ], [ "Rest" ] ], 1.25 ], - [ [ [ "Rest" ], [ 5, -2, 0, -1, -1, -4 ], [ 6, -1, 0, -1, -1, -4 ], [ "Rest" ] ], 1.5 ], - [ [ [ "Rest" ], [ 5, -1, 0, -2, -1, -4 ], [ 6, -1, 0, -1, -1, -4 ], [ "Rest" ] ], 1.25 ], - [ [ [ "Rest" ], [ 5, -1, 0, -1, -1, -5 ], [ 6, -1, 0, -1, -1, -4 ], [ "Rest" ] ], 3.125 ] - ], - [ - [ [ [ "Rest" ], [ 5, -1, 0, -1, -1, -5 ], [ 6, -1, 0, -1, -1, -4 ], [ 5, -1, 0, 0, 0, -5 ] ], 2.625 ], - [ [ [ 3, -1, 0, -1, 0, -5 ], [ 5, -1, 0, -1, -1, -5 ], [ 6, -1, 0, -1, -1, -4 ], [ 5, -1, 0, 0, 0, -5 ] ], 1.375 ], - [ [ [ 3, -1, 0, -1, 0, -5 ], [ 5, -1, 0, -1, -1, -5 ], [ 5, -1, 1, 0, 0, -5 ], [ 5, -1, 0, 0, 0, -5 ] ], 2.625 ] - ], - [ - [ [ [ 3, -1, 0, -1, 0, -5 ], [ 3, 0, 1, 0, 0, -5 ], [ 5, -1, 1, 0, 0, -5 ], [ 5, -1, 0, 0, 0, -5 ] ], 1.125 ], - [ [ [ 2, -1, 1, 0, 0, -5 ], [ 3, 0, 1, 0, 0, -5 ], [ 5, -1, 1, 0, 0, -5 ], [ 5, -1, 0, 0, 0, -5 ] ], 0.875 ], - [ [ [ 2, -1, 1, 0, 0, -5 ], [ 3, 0, 1, 0, 0, -5 ], [ 5, -1, 1, 0, 0, -5 ], [ 4, -1, 1, 1, 0, -5 ] ], 1.5 ], - [ [ [ 2, -1, 1, 0, 0, -5 ], [ 3, -1, 1, 1, 0, -5 ], [ 5, -1, 1, 0, 0, -5 ], [ 4, -1, 1, 1, 0, -5 ] ], 1 ], - [ [ [ 3, -1, 1, -1, 0, -5 ], [ 3, -1, 1, 1, 0, -5 ], [ 5, -1, 1, 0, 0, -5 ], [ 4, -1, 1, 1, 0, -5 ] ], 2.125 ] - ], - [ - [ [ [ 3, -1, 1, -1, 0, -5 ], [ 3, -1, 1, 1, 0, -5 ], [ 4, -1, 2, 1, 0, -5 ], [ 4, -1, 1, 1, 0, -5 ] ], 0.75 ], - [ [ [ 2, -1, 1, 1, 0, -6 ], [ 3, -1, 1, 1, 0, -5 ], [ 4, -1, 2, 1, 0, -5 ], [ 4, -1, 1, 1, 0, -5 ] ], 0.75 ], - [ [ [ 2, -2, 1, 1, 0, -5 ], [ 3, -1, 1, 1, 0, -5 ], [ 4, -1, 2, 1, 0, -5 ], [ 4, -1, 1, 1, 0, -5 ] ], 2 ] - ], - [ - [ [ [ 2, -2, 1, 1, 0, -5 ], [ 3, -1, 1, 1, 0, -5 ], [ "Rest" ], [ 4, -1, 1, 1, 0, -5 ] ], 0.75 ], - [ [ [ 2, -1, 1, 1, -1, -5 ], [ 3, -1, 1, 1, 0, -5 ], [ "Rest" ], [ 4, -1, 1, 1, 0, -5 ] ], 1.125 ], - [ [ [ 2, -1, 1, 1, -1, -5 ], [ 2, -1, 1, 2, 0, -5 ], [ "Rest" ], [ 4, -1, 1, 1, 0, -5 ] ], 1 ], - [ [ [ 2, -1, 1, 1, -1, -5 ], [ 3, -1, 0, 1, 0, -5 ], [ "Rest" ], [ 4, -1, 1, 1, 0, -5 ] ], 1.5 ], - [ [ [ 2, -1, 1, 1, -1, -5 ], [ 2, -1, 1, 1, 0, -4 ], [ "Rest" ], [ 4, -1, 1, 1, 0, -5 ] ], 1.5 ], - [ [ [ 1, -1, 1, 1, 1, -5 ], [ 2, -1, 1, 1, 0, -4 ], [ "Rest" ], [ 4, -1, 1, 1, 0, -5 ] ], 0.75 ], - [ [ [ 1, -1, 1, 1, 1, -5 ], [ 2, 0, 1, 1, 0, -5 ], [ "Rest" ], [ 4, -1, 1, 1, 0, -5 ] ], 1.5 ] - ], - [ - [ [ [ 1, -1, 1, 1, 1, -5 ], [ 2, 0, 1, 1, 0, -5 ], [ "Rest" ], [ 3, 0, 1, 1, 1, -5 ] ], 0.75 ], - [ [ [ 1, -1, 1, 1, 1, -5 ], [ 2, 0, 1, 1, 0, -5 ], [ 3, -1, 1, 2, 1, -5 ], [ 3, 0, 1, 1, 1, -5 ] ], 1.625 ], - [ [ [ 1, -1, 1, 1, 1, -5 ], [ 2, -1, 1, 1, 1, -5 ], [ 3, -1, 1, 2, 1, -5 ], [ 3, 0, 1, 1, 1, -5 ] ], 1.125 ], - [ [ [ 1, -1, 1, 1, 1, -5 ], [ 1, -1, 1, 2, 1, -5 ], [ 3, -1, 1, 2, 1, -5 ], [ 3, 0, 1, 1, 1, -5 ] ], 0.875 ], - [ [ [ 1, -1, 1, 1, 1, -5 ], [ 1, 0, 1, 1, 1, -5 ], [ 3, -1, 1, 2, 1, -5 ], [ 3, 0, 1, 1, 1, -5 ] ], 1.5 ], - [ [ [ 1, -1, 1, 1, 1, -5 ], [ 1, 0, 1, 1, 1, -5 ], [ 4, -1, 0, 1, 1, -5 ], [ 3, 0, 1, 1, 1, -5 ] ], 2.625 ], - [ [ [ "Rest" ], [ 1, 0, 1, 1, 1, -5 ], [ 4, -1, 0, 1, 1, -5 ], [ 3, 0, 1, 1, 1, -5 ] ], 1 ], - [ [ [ "Rest" ], [ 1, 0, 1, 1, 1, -5 ], [ 4, -1, 0, 1, 1, -5 ], [ "Rest" ] ], 1.5 ], - [ [ [ "Rest" ], [ "Rest" ], [ 4, -1, 0, 1, 1, -5 ], [ "Rest" ] ], 1.25 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 2.875 ] - ] - ] -], -"last_changes": -[ - [ [ 1, -1, 1, 1, 1, -5 ], [ 2, 0, 1, 1, 0, -5 ], [ 3, -1, 1, 2, 1, -5 ], [ 3, 0, 1, 1, 1, -5 ] ], - [ [ 1, -1, 1, 1, 1, -5 ], [ 2, -1, 1, 1, 1, -5 ], [ 3, -1, 1, 2, 1, -5 ], [ 3, 0, 1, 1, 1, -5 ] ], - [ [ 1, -1, 1, 1, 1, -5 ], [ 1, -1, 1, 2, 1, -5 ], [ 3, -1, 1, 2, 1, -5 ], [ 3, 0, 1, 1, 1, -5 ] ], - [ [ 1, -1, 1, 1, 1, -5 ], [ 1, 0, 1, 1, 1, -5 ], [ 3, -1, 1, 2, 1, -5 ], [ 3, 0, 1, 1, 1, -5 ] ], - [ [ 1, -1, 1, 1, 1, -5 ], [ 1, 0, 1, 1, 1, -5 ], [ 4, -1, 0, 1, 1, -5 ], [ 3, 0, 1, 1, 1, -5 ] ] -], -"cur_uid": "7c8bc6df", -"ref_uid": "tmp", -"order_seed": 487536, -"dur_seed": 140662, -"motifs_seed": 617352, -"entrances_probs_vals": [ 0, 0.48, 1.7460317460317, 0.58, 1.68, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"passages_probs_vals": [ 0, 0.48, 1.7460317460317, 0.58, 1.68, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0, 0.48, 1.7460317460317, 0.58, 1.68, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ -3600, -627.86377708978 ], [ -3600, 260 ], [ -980.80495356037, 2066 ], [ -627.86377708978, 2053 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 2 ], [ 1, 1, 1, 1 ], [ 3, 0 ] ], - [ [ 1, 3 ], [ 0, 2 ], [ ] ], - [ [ 2 ], [ 1, 0, 3, 1, 0 ], [ ] ], - [ [ 1, 3 ], [ 2, 0, 0 ], [ ] ], - [ [ 3 ], [ 0, 1, 1, 1, 0, 1 ], [ 2 ] ], - [ [ 0 ], [ 3, 2, 1, 1, 1, 2 ], [ ] ] -], -"sus_weights": [ 0.73, 0.49, 0 ], -"order_size": [ 1, 7 ], -"passages_size": [ 0, 5 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/7e170ef8/7e170ef8_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/7e170ef8/7e170ef8_code.scd deleted file mode 100644 index b11446a..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/7e170ef8/7e170ef8_code.scd +++ /dev/null @@ -1,718 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON; - -// model vars -//(model and global vars mostly set by OSC funcs -var curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, orders, susWeights, passagesWeights, passagesSize, orderSize; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var lastXChanges, popSize, exPath, dir, primes, dims, tuples, -seq, group, player, ledgerPath, ledger, currentlyPlayingUID; - - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, min, max, envData; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - durFunc = {arg allowChord; - var res; - res = if(allowChord.not, { - pTable.tableRand * (max - min) + min - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (max - min) + min}); - }).round(0.125); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, durSeed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - allowChord = if((sus ++ silent).includes(ins), { - (sus ++ silent).includes(ins) && (ins != sus.last); - }, { - if(i < (flatOrder.size - 1), {(isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not}, {false}); - }); - dur = passagesDurFunc.value(allowChord); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(isLastOrder, { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - dur = passagesDurFunc.value(allowChord); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); - -genPatterns = {arg inSeq, addr; - var voices, durs, patterns, res, indices, sectionDurs, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - indices = inSeq.collect({arg mSeq, m; mSeq[1]}); - ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - res = Ppar( - voices.flop.collect({arg voice; - var clumps, hdScores, freqs, fDurs; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \instrument, \test, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1) - ) - }) ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \indexPath, "/cur_play_index", - \indexMsg, Pseq(indices.postln, 1), - \seqPath, "/mus_seq", - \seqMsg, Pseq(seq, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - ); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < (maxDepth - 0), { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path; - var file, nameSpaces, modelItems, resString; - file = File(path,"w"); - - nameSpaces = [ - "music_data", "last_changes", - "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size" - ]; - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize - ]; - - resString = [nameSpaces, modelItems].flop.collect({arg item; - var nameSpace, modelItem, depth = 0, insert = " "; - # nameSpace, modelItem = item; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(modelItem.postln, depth).postln - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg model; - var nameSpaces, data; - - //model = File(path, "r").readAllString.parseJSON; - - nameSpaces = [ - "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size" - ]; - - data = nameSpaces.collect({arg nS; msgInterpret.value(model[nS]).postln}); - - data.postln; - - # curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize = data; - - popSize = ranges.size; -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg ledger; ledger = ledger["ledger"]}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - loadModelFile.value(msg[1].asString); -}, \load_model); - - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dFormat, condition, musPath; - msg.postln; - - path = msg[1].asString; - - loadModelFile.value(path); - - refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - lastXChanges = if(refUID == nil, { - [initVoices.value().deepCopy]; - }, { - var file; - refUID.postln; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..2] ++ [entrancesProbVals[3..]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..2] ++ [passagesProbVals[3..]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..2] ++ [exitsProbVals[3..]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - //musPath = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - writeResources.value(path); - - //orders = nil; - //addr.sendMsg("/current_uid", curUID); - //addr.sendMsg("/ledger", prettifyArray.value(ledger, 1).replace("\"", "")); - //addr.sendMsg("/ledger_size", ledger.size); - //addr.sendMsg("/mus_seq", prettifyArray.value(seq, 3)); - addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var newLedger, modelPath, musString, musFile, test1, test2; - msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - curUID = genUID.value; - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - writeResources.value(modelPath); - - File.delete(ledgerPath.postln ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - newLedger = File(ledgerPath.postln, "w"); - ledger = ledger.postln.drop(-1).add(curUID); - newLedger.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - newLedger.close; - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - player.stop; - group.set(\gate, 0); - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var file; - (indexStart + index).postln; - file = File((dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_music" ++ ".json").standardizePath, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, {pSeq = pSeq.add([seq, ledger.size - 1])}); - patterns = genPatterns.value(pSeq, addr); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms; - noHarms = 30; - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) - -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) - - - -"{\"a\": 1}".parseYAML["a"].asInteger; -"{\"a\": 1}".parseJSON["a"].isNumber; - -1223423434123.asHexString.toLower - -Date.getDate.rawSeconds -Date.seed.asHexString.toLower - -n = NetAddr("localhost", 8080); -n.sendMsg("/GET/#", (NetAddr.localAddr.hostname ++ ":" ++ NetAddr.localAddr.port), "/passage_probs_vals"); \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/7e170ef8/7e170ef8_gui_state.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/7e170ef8/7e170ef8_gui_state.json deleted file mode 100644 index 704cf3a..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/7e170ef8/7e170ef8_gui_state.json +++ /dev/null @@ -1,1359 +0,0 @@ -{ - "motif_label": "motif", - "seeds_label": "seeds", - "order": "[\n [ [ 3, 1, 0 ], [ 2 ], [ ] ],\n [ [ 1, 2 ], [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 3 ] ],\n [ [ 3, 2 ], [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ], [ 0 ] ],\n [ [ 2, 3 ], [ 0, 1, 0 ], [ ] ]\n]", - "order_lock": 1, - "order_size": [ - 3, - 8 - ], - "order_size_v2": 8, - "order_size_v1": 3, - "order_size_panel": -1, - "passage_size_v2": 8, - "passage_size_v1": 2, - "passage_size_panel": -1, - "sus_weights": [ - null, - null, - null - ], - "range_matrix": [ - null, - null, - null, - null - ], - "instrumentation": [ - 0, - 0 - ], - "entrances_probs_sync": "passages", - "entrances": -1, - "passages_probs_sync": "passages", - "passages": -1, - "exits_probs_sync": "passages", - "exits": -1, - "dur_panel": 0, - "durations": -1, - "passages_weights": [ - null, - null, - null, - null, - null - ], - "weights": -1, - "seeds_tab_panel": 0, - "weights_seed_lock": 0, - "weights_seed": 534103, - "sus_weights/0_slider_val": 0.21, - "sus_weights/0_slider_slider": 0.21, - "sus_weights/0_slider_input": 0.21, - "sus_weights/0_slider_label": 1, - "sus_weights/0_slider": -1, - "sus_weights/1_slider_val": 0.35, - "sus_weights/1_slider_slider": 0.35, - "sus_weights/1_slider_input": 0.35, - "sus_weights/1_slider_label": 2, - "sus_weights/1_slider": -1, - "sus_weights/2_slider_val": 0.21, - "sus_weights/2_slider_slider": 0.21, - "sus_weights/2_slider_input": 0.21, - "sus_weights/2_slider_label": 3, - "sus_weights/2_slider": -1, - "passages_weights/0_slider_val": 0.49, - "passages_weights/0_slider_slider": 0.49, - "passages_weights/0_slider_input": 0.49, - "passages_weights/0_slider_label": "step", - "passages_weights/0_slider": -1, - "passages_weights/1_slider_val": 0.53, - "passages_weights/1_slider_slider": 0.53, - "passages_weights/1_slider_input": 0.53, - "passages_weights/1_slider_label": "dc", - "passages_weights/1_slider": -1, - "passages_weights/2_slider_val": 0.35, - "passages_weights/2_slider_slider": 0.35, - "passages_weights/2_slider_input": 0.35, - "passages_weights/2_slider_label": "range", - "passages_weights/2_slider": -1, - "passages_weights/3_slider_val": 0.59, - "passages_weights/3_slider_slider": 0.59, - "passages_weights/3_slider_input": 0.59, - "passages_weights/3_slider_label": "registration", - "passages_weights/3_slider": -1, - "passages_weights/4_slider_val": 0.39, - "passages_weights/4_slider_slider": 0.39, - "passages_weights/4_slider_input": 0.39, - "passages_weights/4_slider_label": "hd", - "passages_weights/4_slider": -1, - "range_matrix/0_val_input_min": -853.2067988668555, - "range_matrix/0_val_rslider": [ - -853.2067988668555, - 401 - ], - "range_matrix/0_val_input_max": 401, - "range_matrix/0_val": -1, - "range_matrix/1_val_input_min": -659, - "range_matrix/1_val_rslider": [ - -659, - 880 - ], - "range_matrix/1_val_input_max": 880, - "range_matrix/1_val": -1, - "range_matrix/2_val_input_min": -241, - "range_matrix/2_val_rslider": [ - -241, - 1869 - ], - "range_matrix/2_val_input_max": 1869, - "range_matrix/2_val": -1, - "range_matrix/3_val_input_min": -27, - "range_matrix/3_val_rslider": [ - -27, - 2063 - ], - "range_matrix/3_val_input_max": 2063, - "range_matrix/3_val": -1, - "entrances_probs_chord_slider_val": 0.66, - "entrances_probs_chord_slider_slider": 0.66, - "entrances_probs_chord_slider_input": 0.66, - "entrances_probs_chord_slider_label": "chord prob", - "entrances_probs_chord_slider": -1, - "entrances_probs_vals": [ - 0.63, - 0, - 5, - 0, - 0.5, - 0.23316062176165803, - 0.7094594594594594, - 0.3963730569948187, - 0.8716216216216216, - 0.4948186528497409, - 0.5912162162162162, - 0.5362694300518135, - 0.8614864864864865, - 0.6424870466321243, - 0.5912162162162162, - 0.7901554404145078, - 0.8277027027027027, - 1, - 0.5 - ], - "entrances_probs": -1, - "passages_probs_chord_slider_val": 0.63, - "passages_probs_chord_slider_slider": 0.63, - "passages_probs_chord_slider_input": 0.63, - "passages_probs_chord_slider_label": "chord prob", - "passages_probs_chord_slider": -1, - "passages_probs_vals": [ - 0.63, - 0, - 5, - 0, - 0.5, - 0.23316062176165803, - 0.7094594594594594, - 0.3963730569948187, - 0.8716216216216216, - 0.4948186528497409, - 0.5912162162162162, - 0.5362694300518135, - 0.8614864864864865, - 0.6424870466321243, - 0.5912162162162162, - 0.7901554404145078, - 0.8277027027027027, - 1, - 0.5 - ], - "passages_probs": -1, - "exits_probs_chord_slider_val": 0, - "exits_probs_chord_slider_slider": 0, - "exits_probs_chord_slider_input": 0, - "exits_probs_chord_slider_label": "chord prob", - "exits_probs_chord_slider": -1, - "exits_probs_vals": [ - 0, - 0, - 5, - 0, - 0.5, - 0.23316062176165803, - 0.7094594594594594, - 0.4948186528497409, - 0.5912162162162162, - 0.7901554404145078, - 0.8277027027027027, - 1, - 0.5 - ], - "exits_probs": -1, - "step_env_env_vals": [ - 0, - 5, - 0, - 0, - 0, - 0, - 0.14609053497942387, - 0.7613636363636364, - 0.20164609053497942, - 0.26136363636363635, - 0.24279835390946503, - 0.7215909090909092, - 0.39094650205761317, - 0.875, - 0.4567901234567901, - 0.44318181818181823, - 0.5432098765432098, - 0.34659090909090906, - 0.6481481481481481, - 0.8011363636363636, - 0.6810699588477366, - 0.5170454545454546, - 0.8868312757201646, - 0.49431818181818177, - 0.8868312757201646, - 0.49431818181818177 - ], - "step_env_env_canvas": [ - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 0.14609053497942387, - 0.7613636363636364 - ], - [ - 0.20164609053497942, - 0.26136363636363635 - ], - [ - 0.24279835390946503, - 0.7215909090909092 - ], - [ - 0.39094650205761317, - 0.875 - ], - [ - 0.4567901234567901, - 0.44318181818181823 - ], - [ - 0.5432098765432098, - 0.34659090909090906 - ], - [ - 0.6481481481481481, - 0.8011363636363636 - ], - [ - 0.6810699588477366, - 0.5170454545454546 - ], - [ - 0.8868312757201646, - 0.49431818181818177 - ], - [ - 0.8868312757201646, - 0.49431818181818177 - ], - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - "step_env_env_size": 12, - "step_env_env_flatten": 0, - "step_env_env_rslider": [ - 0, - 5 - ], - "step_env_env_rslider_v2": 5, - "step_env_env_rslider_v1": 0, - "step_env_env_mpos": "", - "step_env_env": -1, - "entrances_probs_dur_env_vals": [ - 0.515267175572519, - 4.599236641221374, - 0, - 0.5, - 0.2772020725388601, - 0.7972972972972973, - 0.45077720207253885, - 0.8783783783783784, - 0.5, - 0.5, - 0.727979274611399, - 0.45270270270270274, - 0.7357512953367875, - 0.6486486486486487, - 0.8911917098445595, - 0.7905405405405406, - 1, - 0.5 - ], - "entrances_probs_dur_env_canvas": [ - [ - 0, - 0.5 - ], - [ - 0.2772020725388601, - 0.7972972972972973 - ], - [ - 0.45077720207253885, - 0.8783783783783784 - ], - [ - 0.5, - 0.5 - ], - [ - 0.727979274611399, - 0.45270270270270274 - ], - [ - 0.7357512953367875, - 0.6486486486486487 - ], - [ - 0.8911917098445595, - 0.7905405405405406 - ], - [ - 1, - 0.5 - ], - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - "entrances_probs_dur_env_size": 8, - "entrances_probs_dur_env_flatten": 0, - "entrances_probs_dur_env_rslider": [ - 0.515267175572519, - 4.599236641221374 - ], - "entrances_probs_dur_env_rslider_v2": 4.599236641221374, - "entrances_probs_dur_env_rslider_v1": 0.515267175572519, - "entrances_probs_dur_env_mpos": "", - "entrances_probs_dur_env": -1, - "passages_probs_dur_env_vals": [ - 0, - 5, - 0, - 0.5, - 0.23316062176165803, - 0.7094594594594594, - 0.3963730569948187, - 0.8716216216216216, - 0.4948186528497409, - 0.5912162162162162, - 0.5362694300518135, - 0.8614864864864865, - 0.6424870466321243, - 0.5912162162162162, - 0.7901554404145078, - 0.8277027027027027, - 1, - 0.5 - ], - "passages_probs_dur_env_canvas": [ - [ - 0, - 0.5 - ], - [ - 0.23316062176165803, - 0.7094594594594594 - ], - [ - 0.3963730569948187, - 0.8716216216216216 - ], - [ - 0.4948186528497409, - 0.5912162162162162 - ], - [ - 0.5362694300518135, - 0.8614864864864865 - ], - [ - 0.6424870466321243, - 0.5912162162162162 - ], - [ - 0.7901554404145078, - 0.8277027027027027 - ], - [ - 1, - 0.5 - ], - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - "passages_probs_dur_env_size": 8, - "passages_probs_dur_env_flatten": 0, - "passages_probs_dur_env_rslider": [ - 0, - 5 - ], - "passages_probs_dur_env_rslider_v2": 5, - "passages_probs_dur_env_rslider_v1": 0, - "passages_probs_dur_env_mpos": "", - "passages_probs_dur_env": -1, - "exits_probs_dur_env_vals": [ - 0, - 5, - 0, - 0.5, - 0.5, - 0.5, - 1, - 0.5 - ], - "exits_probs_dur_env_canvas": [ - [ - 0, - 0.5 - ], - [ - 0.5, - 0.5 - ], - [ - 1, - 0.5 - ], - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - "exits_probs_dur_env_size": 3, - "exits_probs_dur_env_flatten": 0, - "exits_probs_dur_env_rslider": [ - 0, - 5 - ], - "exits_probs_dur_env_rslider_v2": 5, - "exits_probs_dur_env_rslider_v1": 0, - "exits_probs_dur_env_mpos": "", - "exits_probs_dur_env": -1, - "mus_seq": [ - [ - [ - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - "Rest" - ], - [ - "Rest" - ] - ], - 0 - ], - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -3, - 0, - 1, - -1 - ], - [ - "Rest" - ] - ], - 1.75 - ], - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 1.75 - ], - [ - [ - [ - 0, - 1, - -3, - 0, - 2, - -1 - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 0.75 - ], - [ - [ - [ - 1, - 1, - -2, - -2, - 1, - 0 - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 0.625 - ], - [ - [ - [ - 1, - 1, - -3, - -1, - 0, - 0 - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 0.625 - ], - [ - [ - [ - 1, - 0, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 1.75 - ] - ], - [ - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 0 - ], - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -3, - -1, - 1, - 0 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 1.75 - ], - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 0, - 1, - -2, - 0, - 1, - 0 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 1.375 - ], - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 0, - 2, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 0.75 - ], - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 0, - 1, - -2, - -1, - 2, - 0 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 1.75 - ], - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 0, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 1.875 - ], - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -2, - -1, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 1 - ] - ], - [ - [ - [ - [ - 1, - 0, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 1, - 1, - -2, - -1, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 0 - ], - [ - [ - [ - 1, - 0, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 2, - 0, - -3, - -1, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 1.625 - ], - [ - [ - [ - 1, - 0, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 0, - 1, - -1, - -1, - 1, - 0 - ], - [ - 1, - 1, - -2, - -1, - 0, - 0 - ] - ], - 1.75 - ], - [ - [ - [ - 1, - 0, - -3, - 0, - 1, - -1 - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 0, - 1, - -1, - -1, - 1, - 0 - ], - [ - "Rest" - ] - ], - 0 - ], - [ - [ - [ - "Rest" - ], - [ - 1, - 1, - -2, - -1, - 1, - 0 - ], - [ - 0, - 1, - -1, - -1, - 1, - 0 - ], - [ - "Rest" - ] - ], - 1.875 - ], - [ - [ - [ - "Rest" - ], - [ - "Rest" - ], - [ - 0, - 1, - -1, - -1, - 1, - 0 - ], - [ - "Rest" - ] - ], - 0 - ], - [ - [ - [ - "Rest" - ], - [ - "Rest" - ], - [ - "Rest" - ], - [ - "Rest" - ] - ], - 0.875 - ] - ] - ] - ], - "root": [ - 0.20743639921722112, - 0 - ], - "order_seed": 798574, - "dur_seed": 884869, - "passages_size": [ - 0, - 10 - ], - "dur_seed_lock": 1, - "order_seed_lock": 0, - "seeds_panel": -1, - "motif_panel": [ - 0, - 0 - ], - "ref_uid": "6f1a789f", - "cur_uid": "7e170ef8" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/7e170ef8/7e170ef8_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/7e170ef8/7e170ef8_mus_model.json deleted file mode 100644 index c9b8807..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/7e170ef8/7e170ef8_mus_model.json +++ /dev/null @@ -1,79 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1.75 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0 ], - [ [ [ "Rest" ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0.625 ], - [ [ [ "Rest" ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 0.875 ], - [ [ [ "Rest" ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 1.375 ], - [ [ [ "Rest" ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 0 ], - [ [ [ "Rest" ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 0.5 ], - [ [ [ "Rest" ], [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 0 ], - [ [ [ "Rest" ], [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1.25 ], - [ [ [ "Rest" ], [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ] ], 0 ], - [ [ [ "Rest" ], [ 0, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ] ], 1.875 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ] ], 1.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 1.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ] ], 1.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 1 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 1 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 1 ] ], 1.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 1 ] ], 1.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ] ], 1.375 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ] ], 1.375 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ], [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ] ], 1.125 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 1, 0 ], [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ] ], 1.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ] ], 1.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ] ], 1.125 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ] ], 1.25 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ] ], 1.25 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 1.25 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, -1, 0, 0, 0, 1 ] ], 1.5 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.25 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ "Rest" ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, -1, 0, 0, 0, 1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ] -], -"cur_uid": "7e170ef8", -"ref_uid": "nil", -"order_seed": 142640, -"dur_seed": 629022, -"motifs_seed": 973728, -"entrances_probs_vals": [ 0.75, 0.5, 2, 0, 0.5, 0.26424870466321, 0.75675675675676, 0.5, 0.5, 0.58549222797927, 0.72635135135135, 1, 0.5 ], -"passages_probs_vals": [ 0.75, 0.5, 2, 0, 0.5, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0.75, 0.5, 2, 0, 0.5, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ -384, 2400 ], [ -507, 2400 ], [ -282, 2237 ], [ -1200, 2053 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 2 ], [ 3, 1, 3, 3, 3, 1, 1, 3, 3, 1 ], [ 0 ] ], - [ [ 0 ], [ 1, 2, 3, 3, 1, 3, 1, 3 ], [ ] ], - [ [ 0, 3 ], [ 1, 1, 1, 1, 1, 1 ], [ 2 ] ], - [ [ 1, 2, 0 ], [ 3, 3, 3, 3 ], [ ] ] -], -"sus_weights": [ 0.75, 0.69, 0.75 ], -"order_size": [ 2, 6 ], -"passages_size": [ 0, 10 ] -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/7fd4d544/7fd4d544_code.scd b/resources/resources_bak_2024_01_03/piece_ledger_pas/7fd4d544/7fd4d544_code.scd deleted file mode 100644 index 830a192..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/7fd4d544/7fd4d544_code.scd +++ /dev/null @@ -1,894 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - pDistance.gaussCurve(1, mean, sd) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = 1/pow(hdSum.value(voices.deepCopy.put(ins, candidate)), 2); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~msg.postln; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - //res.postln; - if(res.every({arg char; char.isDecDigit}), {res = res.asInteger}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, passagesWeights, orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "passages_weights", "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - ledger = ledger.drop(-1).add(curUID); - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - player.stop; - group.set(\gate, 0); - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - -) - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = 30; - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs, hierarchicalDust; - - hierarchicalDust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) - ); - - sigs = [~stringModelBusArray, ~sineBusArray, ~bassBusArray, ~hdustBusArray, ~samplerBusArray].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -mixer = Synth.tail(~group, \mixer); -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/piece_ledger_pas/7fd4d544/7fd4d544_mus_model.json b/resources/resources_bak_2024_01_03/piece_ledger_pas/7fd4d544/7fd4d544_mus_model.json deleted file mode 100644 index e83ee7f..0000000 --- a/resources/resources_bak_2024_01_03/piece_ledger_pas/7fd4d544/7fd4d544_mus_model.json +++ /dev/null @@ -1,44 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 1, 0, 0, 0, 1, 0 ] ], 4.75 ], - [ [ [ "Rest" ], [ -1, 0, 0, 1, 1, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 1, 0 ] ], 1.125 ], - [ [ [ 0, 0, 0, -1, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 1, 0 ] ], 1 ], - [ [ [ 0, 0, 0, -1, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ], [ 2, 0, 0, 0, 1, -1 ], [ 1, 0, 0, 0, 1, 0 ] ], 5.125 ], - [ [ [ 0, 0, 0, -1, 1, 0 ], [ "Rest" ], [ 2, 0, 0, 0, 1, -1 ], [ 1, 0, 0, 0, 1, 0 ] ], 1.125 ], - [ [ [ 0, 0, 0, -1, 1, 0 ], [ "Rest" ], [ 2, 0, 0, 0, 1, -1 ], [ "Rest" ] ], 0.875 ], - [ [ [ "Rest" ], [ "Rest" ], [ 2, 0, 0, 0, 1, -1 ], [ "Rest" ] ], 0.875 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 4.375 ] - ] - ] -], -"last_changes": -[ - [ [ 0, -1, 0, 0, 1, 0 ], [ 0, 0, -1, 0, 1, 0 ], [ 1, 0, 1, 0, 1, 0 ], [ 1, 0, 0, 0, 1, 0 ] ], - [ [ 0, -1, 0, 0, 1, 0 ], [ 0, 0, -1, 0, 1, 0 ], [ 2, 0, 0, -1, 1, 0 ], [ 1, 0, 0, 0, 1, 0 ] ], - [ [ 0, -1, 0, 0, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ], [ 2, 0, 0, -1, 1, 0 ], [ 1, 0, 0, 0, 1, 0 ] ], - [ [ 0, 0, 0, -1, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ], [ 2, 0, 0, -1, 1, 0 ], [ 1, 0, 0, 0, 1, 0 ] ], - [ [ 0, 0, 0, -1, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ], [ 2, 0, 0, 0, 1, -1 ], [ 1, 0, 0, 0, 1, 0 ] ] -], -"cur_uid": "7fd4d544", -"ref_uid": "tmp", -"order_seed": 159820, -"dur_seed": 341194, -"motifs_seed": 928268, -"entrances_probs_vals": [ 0, 1.67, 4.8015873015873, 0.24725274725275, 1.15, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"passages_probs_vals": [ 0, 1.67, 4.8015873015873, 0.24725274725275, 1.15, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0, 1.83, 4.8809523809524, 0.24725274725275, 1.15, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ -1100, 460.68111455108 ], [ -507, 1084.8297213622 ], [ 884.21052631579, 2237 ], [ 1040.2476780186, 2053 ] ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"order": -[ - [ [ 3 ], [ 1, 0, 2 ], [ ] ] -], -"sus_weights": [ 0.73, 0.23, 0 ], -"order_size": [ 1, 2 ], -"passages_size": [ 0, 1 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1.json b/resources/resources_bak_2024_01_03/string_quartet_1.json deleted file mode 100644 index 8e41d98..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1.json +++ /dev/null @@ -1,25 +0,0 @@ -{ -"ledger": -[ - "4a8a6e53", - "66f6a618", - "490b1e6e", - "46985d14", - "761e4585", - "6fb60ab6", - "79e0a4a7", - "43b009ff", - "7d3c9a80", - "4b7745df", - "6ed95c4c", - "6d635e88", - "4e7d35e5", - "7edbdceb", - "784130cc", - "443ec222", - "52c9a980", - "4200a90d", - "61ce9067", - "774ed940" -] -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/4200a90d_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/4200a90d_code.scd deleted file mode 100644 index a98b916..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/4200a90d_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/4200a90d_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/4200a90d_mus_model.json deleted file mode 100644 index de04cf3..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/4200a90d_mus_model.json +++ /dev/null @@ -1,58 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 1, 0, 1, -2, 1, 1 ] ], 2 ], - [ [ [ "Rest" ], [ "Rest" ], [ 1, 0, 0, -2, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], 1.5 ] - ], - [ - [ [ [ "Rest" ], [ 1, -1, 1, -2, 2, 0 ], [ 1, 0, 0, -2, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], 2 ], - [ [ [ "Rest" ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], 0 ], - [ [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], 0.625 ], - [ [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], 0 ], - [ [ [ -1, -1, 1, -1, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], 1.25 ], - [ [ [ -1, -1, 1, -2, 2, 1 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], 0 ], - [ [ [ -1, -1, 1, -2, 2, 1 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], 0 ], - [ [ [ -1, -1, 1, -2, 2, 1 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 1 ], [ 2, -1, 0, -2, 2, 0 ] ], 1.25 ], - [ [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 1 ], [ 2, -1, 0, -2, 2, 0 ] ], 1.25 ], - [ [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -1, 2, 0 ], [ 2, -1, 0, -2, 2, 0 ] ], 1.125 ], - [ [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -1, 2, 0 ], [ 1, -1, 1, -2, 3, 0 ] ], 2.25 ], - [ [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ "Rest" ], [ 1, -1, 1, -2, 3, 0 ] ], 1.5 ], - [ [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ "Rest" ], [ 1, -1, 1, -2, 3, 0 ] ], 0.875 ], - [ [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ "Rest" ], [ "Rest" ] ], 1.125 ] - ] - ] -], -"last_changes": -[ - [ [ -1, -1, 1, -2, 2, 1 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ -1, -1, 1, -2, 2, 1 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 1 ], [ 2, -1, 0, -2, 2, 0 ] ], - [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 1 ], [ 2, -1, 0, -2, 2, 0 ] ], - [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -1, 2, 0 ], [ 2, -1, 0, -2, 2, 0 ] ], - [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -1, 2, 0 ], [ 1, -1, 1, -2, 3, 0 ] ] -], -"cur_uid": "4200a90d", -"ref_uid": "6d635e88", -"order_seed": 516056, -"dur_seed": 358555, -"motifs_seed": 168145, -"entrances_probs_vals": [ 0.18, 0.28, 1.4285714285714, 0.82, 2.0054945054945, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0.29, 0, 1.1111111111111, 0.65934065934066, 1.37, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0.18, 0.28, 1.4285714285714, 0.82, 2.0054945054945, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2411.1455108359, -850.77399380805 ], [ -1872, 450 ], [ -479, 1304.0247678019 ], [ -368, 1173.9938080495 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.082304526748971, 0.99431818181818, 0.33950617283951, 0, 0.72839506172839, 0, 1, 0 ], -"passages_weights": [ 0.35, 0.42, 0.75, 0.9, 0.93 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 3 ], [ 2 ], [ 0, 1 ] ], - [ [ 1 ], [ 2, 0, 2, 0, 0, 2, 3, 0, 2, 3 ], [ ] ] -], -"sus_weights": [ 0.41, 0, 0 ], -"order_size": [ 2, 6 ], -"passages_size": [ 0, 5 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/lilypond/part_I.ly deleted file mode 100644 index bcf7780..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/lilypond/part_I.ly +++ /dev/null @@ -1,18 +0,0 @@ -{ - { ais'1^\markup { \pad-markup #0.2 "+41"} ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'2 ~ ais'8.[ a'16^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }}] ~ a'4 ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'2 fis'2^\markup { \pad-markup #0.2 "+1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↑" }} ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'2. ~ fis'16[ r8.]} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/lilypond/part_II.ly deleted file mode 100644 index b74e7bb..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/lilypond/part_II.ly +++ /dev/null @@ -1,18 +0,0 @@ -{ - { r1 } - \bar "|" - { g'1^\markup { \pad-markup #0.2 "-46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }} ~ } - \bar "|" - { g'2. f'4^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } - \bar "|" - { f'16[ gis'8.^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ gis'4 ~ gis'8.[ a'16^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ a'4 ~ } - \bar "|" - { a'2. ~ a'8.[ ais'16^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }}] ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'2 ~ ais'8[ r8] r4 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/lilypond/part_III.ly deleted file mode 100644 index 11cd320..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/lilypond/part_III.ly +++ /dev/null @@ -1,18 +0,0 @@ -{ - { r1 } - \bar "|" - { r2. c'4^\markup { \pad-markup #0.2 "+49"} ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/lilypond/part_IV.ly deleted file mode 100644 index 5e43176..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4200a90d/lilypond/part_IV.ly +++ /dev/null @@ -1,18 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2. c4^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { c16[ ais,8.^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }}] ~ ais,4 ~ ais,8.[ a,16^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }}] ~ a,4 ~ } - \bar "|" - { a,4 ~ a,16[ g,8.^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↓" }}] ~ g,2 ~ } - \bar "|" - { g,1 ~ } - \bar "|" - { g,1 ~ } - \bar "|" - { g,1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/43b009ff_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/43b009ff_code.scd deleted file mode 100644 index a98b916..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/43b009ff_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/43b009ff_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/43b009ff_mus_model.json deleted file mode 100644 index 3c475af..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/43b009ff_mus_model.json +++ /dev/null @@ -1,48 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 5.75 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 2.75 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ 3, -3, 0, -1, 1, 0 ] ], 1.75 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 3, -2, 0, -2, 1, 0 ], [ 3, -3, 0, -1, 1, 0 ] ], 1.5 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 3, -2, 0, -2, 1, 0 ], [ 2, -2, 0, -1, 2, 0 ] ], 4.125 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ 2, -2, 0, -1, 2, 0 ] ], 0.875 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ 2, -2, 0, -1, 2, 0 ] ], 1 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0.875 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 7.375 ] - ] - ] -], -"last_changes": -[ - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ 1, -1, 0, 0, 1, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ 3, -3, 0, -1, 1, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 3, -2, 0, -2, 1, 0 ], [ 3, -3, 0, -1, 1, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 3, -2, 0, -2, 1, 0 ], [ 2, -2, 0, -1, 2, 0 ] ] -], -"cur_uid": "43b009ff", -"ref_uid": 62820081, -"order_seed": 216475, -"dur_seed": 323751, -"motifs_seed": 466146, -"entrances_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -3600, -312 ], [ -1872, 1378 ], [ -145, 1583 ], [ -182, 1527 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.082304526748971, 0.99431818181818, 0.14197530864198, 0, 1, 0 ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 1, 0 ], [ 3, 2, 3 ], [ ] ] -], -"sus_weights": [ 0, 0.65, 0 ], -"order_size": [ 1, 1 ], -"passages_size": [ 1, 6 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/lilypond/part_I.ly deleted file mode 100644 index af37609..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/lilypond/part_I.ly +++ /dev/null @@ -1,28 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r4 b'2.^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } - \bar "|" - { b'2. ~ b'8[ b'8^\markup { \pad-markup #0.2 "+30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↑" }}] ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'2. ~ b'8[ r8] } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/lilypond/part_II.ly deleted file mode 100644 index 5c63449..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/lilypond/part_II.ly +++ /dev/null @@ -1,28 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r8[ gis'8^\markup { \pad-markup #0.2 "+10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }}] ~ gis'2. ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'2. ~ gis'8.[ r16] } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/lilypond/part_III.ly deleted file mode 100644 index 0795a41..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/lilypond/part_III.ly +++ /dev/null @@ -1,28 +0,0 @@ -{ - { fis'1^\markup { \pad-markup #0.2 "-21"} ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'4 ~ fis'8[ r8] r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/lilypond/part_IV.ly deleted file mode 100644 index ce1dd80..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/43b009ff/lilypond/part_IV.ly +++ /dev/null @@ -1,28 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2. r8[ cis'8^\markup { \pad-markup #0.2 "-19"}] ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'4 ~ cis'16[ r8.] r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/443ec222/443ec222_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/443ec222/443ec222_code.scd deleted file mode 100644 index a98b916..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/443ec222/443ec222_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/443ec222/443ec222_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/443ec222/443ec222_mus_model.json deleted file mode 100644 index 26d2794..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/443ec222/443ec222_mus_model.json +++ /dev/null @@ -1,54 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 1, 0, 1, -2, 1, 1 ] ], 1.75 ], - [ [ [ "Rest" ], [ "Rest" ], [ 1, 0, 1, -2, 1, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], 1.5 ] - ], - [ - [ [ [ "Rest" ], [ "Rest" ], [ 1, 0, 1, -2, 1, 0 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ 1, -1, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 0 ], [ "Rest" ] ], 1.5 ], - [ [ [ "Rest" ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 2, -2, 2, 0 ], [ "Rest" ] ], 0 ], - [ [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 2, -2, 2, 0 ], [ "Rest" ] ], 0.75 ], - [ [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ "Rest" ] ], 0.75 ], - [ [ [ -1, -1, 1, -1, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ "Rest" ] ], 0.625 ], - [ [ [ 0, -1, 0, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ "Rest" ] ], 2.125 ], - [ [ [ "Rest" ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ "Rest" ] ], 1.125 ], - [ [ [ "Rest" ], [ 1, -1, 1, -2, 2, 0 ], [ "Rest" ], [ "Rest" ] ], 0.625 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 5.25 ] - ] - ] -], -"last_changes": -[ - [ [ 1, -1, 1, -3, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 2, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 2, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ -1, -1, 1, -1, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ 0, -1, 0, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ] -], -"cur_uid": "443ec222", -"ref_uid": "6d635e88", -"order_seed": 516056, -"dur_seed": 358555, -"motifs_seed": 962315, -"entrances_probs_vals": [ 0.18, 0.28, 1.4285714285714, 0.47, 1.62, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0.29, 0, 1.1111111111111, 0.65934065934066, 1.37, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0.18, 0.28, 1.4285714285714, 0.47, 1.62, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2411.1455108359, -850.77399380805 ], [ -1872, 450 ], [ -479, 1304.0247678019 ], [ -368, 1173.9938080495 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.082304526748971, 0.99431818181818, 0.33950617283951, 0, 0.72839506172839, 0, 1, 0 ], -"passages_weights": [ 0.35, 0.42, 0.75, 0.9, 0.93 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 3 ], [ 2 ], [ 0, 1 ] ], - [ [ 1 ], [ 2, 0, 2, 0, 0 ], [ 3 ] ] -], -"sus_weights": [ 0.41, 0, 0 ], -"order_size": [ 2, 6 ], -"passages_size": [ 0, 5 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/443ec222/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/443ec222/lilypond/part_I.ly deleted file mode 100644 index da8950a..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/443ec222/lilypond/part_I.ly +++ /dev/null @@ -1,18 +0,0 @@ -{ - { ais'1^\markup { \pad-markup #0.2 "+41"} ~ } - \bar "|" - { ais'2 ~ ais'8[ r8] r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/443ec222/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/443ec222/lilypond/part_II.ly deleted file mode 100644 index 3245478..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/443ec222/lilypond/part_II.ly +++ /dev/null @@ -1,18 +0,0 @@ -{ - { r2. r8[ d'8^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↓" }}] ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'4 ~ d'8[ e'8^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}] ~ e'4 f'4^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'16[ r8.] r2. } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/443ec222/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/443ec222/lilypond/part_III.ly deleted file mode 100644 index 0f68e02..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/443ec222/lilypond/part_III.ly +++ /dev/null @@ -1,18 +0,0 @@ -{ - { r1 } - \bar "|" - { r2 r8[ c'8^\markup { \pad-markup #0.2 "+49"}] ~ c'4 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'4 ~ c'8[ r8] r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/443ec222/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/443ec222/lilypond/part_IV.ly deleted file mode 100644 index a524c1b..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/443ec222/lilypond/part_IV.ly +++ /dev/null @@ -1,18 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r4 r8[ c8^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ c2 ~ } - \bar "|" - { c8[ ais,8^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }}] ~ ais,8.[ a,16^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }}] ~ a,2 ~ } - \bar "|" - { a,2 r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4526b76b/4526b76b_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/4526b76b/4526b76b_code.scd deleted file mode 100644 index 8e9fe42..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4526b76b/4526b76b_code.scd +++ /dev/null @@ -1,943 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4526b76b/4526b76b_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/4526b76b/4526b76b_mus_model.json deleted file mode 100644 index 7489563..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4526b76b/4526b76b_mus_model.json +++ /dev/null @@ -1,44 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 1, -1, 0, -1, 1, -1 ], [ "Rest" ] ], 0.625 ], - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 1, -1 ], [ "Rest" ] ], 1.625 ], - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 1, -1 ], [ 3, -1, 0, -2, 1, -1 ] ], 1.625 ], - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 1, -1 ], [ 3, -1, 0, -1, 1, -2 ] ], 11 ], - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ 3, -1, 0, -1, 1, -2 ] ], 1.375 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 3, -1, 0, -1, 1, -2 ] ], 1.5 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 6.25 ] - ] - ] -], -"last_changes": -[ - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 1, -1 ], [ 1, 0, 0, -1, 1, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 1, -1 ], [ 3, -1, 0, -2, 1, -1 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 1, -1 ], [ 3, -1, 0, -1, 1, -2 ] ] -], -"cur_uid": "4526b76b", -"ref_uid": "6fb60ab6", -"order_seed": 785868, -"dur_seed": 994115, -"motifs_seed": 805843, -"entrances_probs_vals": [ 0.34, 0, 10, 0.5, 2, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0.34, 0, 10, 0.5, 2.12, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0.34, 0, 10, 0.5, 2.12, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -3600, -312 ], [ -1872, 1378 ], [ -145, 1583 ], [ -182, 1527 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.082304526748971, 0.99431818181818, 0.14197530864198, 0, 1, 0 ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 2, 1 ], [ 3, 3 ], [ 0 ] ] -], -"sus_weights": [ 0.75, 0.25, 0.25 ], -"order_size": [ 1, 4 ], -"passages_size": [ 0, 3 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/46985d14/46985d14_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/46985d14/46985d14_code.scd deleted file mode 100644 index 3eb3cbd..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/46985d14/46985d14_code.scd +++ /dev/null @@ -1,1058 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \".." +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - -~transcribe.value(~seq, dir); - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, attack, release = 1, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = rrand(20, 40); - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - //sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * amp * EnvGen.kr(Env.adsr(attack, 0.3, 0.9, release, 0.9, -3), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); - //Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.sine(dur), gate, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs; - - sigs = [~stringModelBusArray, ~sineBusArray/*, ~bassBusArray, ~hdustBusArray, ~samplerBusArray*/].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -/* -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -*/ -mixer = Synth.tail(~group, \mixer); - -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -/* -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -*/ -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/46985d14/46985d14_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/46985d14/46985d14_mus_model.json deleted file mode 100644 index de147a2..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/46985d14/46985d14_mus_model.json +++ /dev/null @@ -1,85 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 0, -1, 0, 0, 1, 0 ], [ "Rest" ] ], 1.75 ], - [ [ [ -1, -1, 0, 1, 1, 0 ], [ "Rest" ], [ 0, -1, 0, 0, 1, 0 ], [ "Rest" ] ], 0 ], - [ [ [ -1, -1, 0, 1, 1, 0 ], [ "Rest" ], [ 0, -1, 0, 0, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ] ], 0 ], - [ [ [ -1, -1, 0, 1, 1, 0 ], [ -1, -1, 0, 0, 1, 1 ], [ 0, -1, 0, 0, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ] ], 1.25 ], - [ [ [ 0, -1, -1, 0, 1, 0 ], [ -1, -1, 0, 0, 1, 1 ], [ 0, -1, 0, 0, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ] ], 1.75 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ -1, -1, 0, 0, 1, 1 ], [ 0, -1, 0, 0, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ] ], 0 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ -1, -1, 0, 0, 1, 1 ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -2, 0, 0, 1, 0 ] ], 0 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ -1, -1, 0, 1, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -2, 0, 0, 1, 0 ] ], 0.875 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -2, 0, 0, 1, 0 ] ], 0 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -1, 0, 0, 1, -1 ] ], 1.625 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 1, -2, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -1, 0, 0, 1, -1 ] ], 1.75 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -1, 0, 0, 1, -1 ] ], 0 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 0.875 ] - ], - [ - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ -1, 0, 1, 0, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 0.625 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, -1 ], [ 1, -1, 0, -1, 1, 0 ] ], 1.625 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ -1, 0, 0, 0, 2, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 1.125 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, -1, -1, -1, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 1 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 0.5 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, -1, 0, -1, 1, 1 ], [ 1, -1, 0, -1, 1, 0 ] ], 1.625 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 1.5 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, -1 ], [ 1, -1, 0, -1, 1, 0 ] ], 0.5 ] - ], - [ - [ [ [ 1, -2, 0, -1, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, -1 ], [ 1, -1, 0, -1, 1, 0 ] ], 0.5 ], - [ [ [ 0, 0, 0, -1, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, -1 ], [ 1, -1, 0, -1, 1, 0 ] ], 1.5 ], - [ [ [ -1, 0, 0, 1, 1, -1 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, -1 ], [ 1, -1, 0, -1, 1, 0 ] ], 1.5 ], - [ [ [ 1, -1, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, -1 ], [ 1, -1, 0, -1, 1, 0 ] ], 1.125 ] - ], - [ - [ [ [ 1, -1, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, -1 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, -1 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ "Rest" ] ], 1.375 ] - ], - [ - [ [ [ "Rest" ], [ 0, 0, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 1.75 ], - [ [ [ 0, -1, 0, -1, 2, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 1.875 ], - [ [ [ -1, -1, 0, 0, 1, 1 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 0.75 ], - [ [ [ 0, -1, -1, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 1.25 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 1 ], - [ [ [ 1, -2, 0, -1, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 1.375 ], - [ [ [ 1, -1, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 2 ], - [ [ [ 1, -1, 0, -1, 0, 0 ], [ "Rest" ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 0 ], - [ [ [ 1, -1, 0, -1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 1, -1, 0, -1, 1, 0 ] ], 4.75 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 1, -1, 0, -1, 1, 0 ] ], 8.875 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 0, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ] -], -"cur_uid": "46985d14", -"ref_uid": "nil", -"order_seed": 209164, -"dur_seed": 417909, -"motifs_seed": 885208, -"entrances_probs_vals": [ 0.34, 0, 10, 0.5, 2, 0, 0.5, 0.24509803921569, 0.89189189189189, 0.5, 1, 0.5, 0.5, 0.8562091503268, 0.69932432432432, 1, 0.5 ], -"passages_probs_vals": [ 0.34, 0, 10, 0.5, 2, 0, 0.5, 0.24509803921569, 0.89189189189189, 0.5, 1, 0.5, 0.5, 0.8562091503268, 0.69932432432432, 1, 0.5 ], -"exits_probs_vals": [ 0.34, 0, 10, 0.5, 2, 0, 0.5, 0.24509803921569, 0.89189189189189, 0.5, 1, 0.5, 0.5, 0.8562091503268, 0.69932432432432, 1, 0.5 ], -"ranges": [ [ -1200, 2400 ], [ -1200, 2400 ], [ -1200, 2400 ], [ -1200, 2400 ] ], -"step_probs_vals": [ 0, 1200, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 2 ], [ 0, 0, 0, 0 ], [ 1, 3 ] ] -], -"sus_weights": [ 0.75, 0.75, 0.75 ], -"order_size": [ 1, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "true", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/46985d14/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/46985d14/lilypond/part_I.ly deleted file mode 100644 index f38f2bd..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/46985d14/lilypond/part_I.ly +++ /dev/null @@ -1,50 +0,0 @@ -{ - { r2. r8[ d'8^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }}] ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'4 ~ d'8[ dis'8^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }}] ~ dis'4 ~ dis'16[ d'8.^\markup { \pad-markup #0.2 "+9"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↓" }}] ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'2 cis'2^\markup { \pad-markup #0.2 "-19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }} ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'2 r2 } - \bar "|" - { r8.[ cis'16^\markup { \pad-markup #0.2 "-19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }}] ~ cis'2. ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/46985d14/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/46985d14/lilypond/part_II.ly deleted file mode 100644 index 2bae7a3..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/46985d14/lilypond/part_II.ly +++ /dev/null @@ -1,50 +0,0 @@ -{ - { ais1^\markup { \pad-markup #0.2 "+49"} ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais2. ~ ais8.[ a16^\markup { \pad-markup #0.2 "+38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ } - \bar "|" - { a4 a2.^\markup { \pad-markup #0.2 "+11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }} ~ } - \bar "|" - { a16[ b8.^\markup { \pad-markup #0.2 "+3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }}] ~ b4 ~ b8[ a8^\markup { \pad-markup #0.2 "-6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }}] ~ a4 ~ } - \bar "|" - { a8[ gis8^\markup { \pad-markup #0.2 "-18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}] ~ gis8[ a8^\markup { \pad-markup #0.2 "+21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }}] ~ a2 ~ } - \bar "|" - { a8.[ ais16^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ ais2 ~ ais8.[ a16^\markup { \pad-markup #0.2 "+11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a2 ais2^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais8.[ r16] r2. } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/46985d14/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/46985d14/lilypond/part_III.ly deleted file mode 100644 index 3ee54a1..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/46985d14/lilypond/part_III.ly +++ /dev/null @@ -1,50 +0,0 @@ -{ - { r2. r8[ g8^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }}] ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g4 ~ g8[ gis8^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}] ~ gis4 ~ gis16[ cis'8.^\markup { \pad-markup #0.2 "-19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }}] ~ } - \bar "|" - { cis'2 ~ cis'8[ dis'8^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }}] ~ dis'4 ~ } - \bar "|" - { dis'2 fis'2^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'8.[ r16] r2. } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/46985d14/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/46985d14/lilypond/part_IV.ly deleted file mode 100644 index f0e3f84..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/46985d14/lilypond/part_IV.ly +++ /dev/null @@ -1,50 +0,0 @@ -{ - { r2. r8[ gis8^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}] ~ } - \bar "|" - { gis2 g2^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }} ~ } - \bar "|" - { g4 ~ g8[ fis8^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }}] ~ fis2 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis8.[ fis16^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }}] ~ fis8.[ gis16^\markup { \pad-markup #0.2 "-18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }}] ~ gis2 ~ } - \bar "|" - { gis8.[ g16^\markup { \pad-markup #0.2 "-20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}] ~ g2 ~ g8.[ g16^\markup { \pad-markup #0.2 "+29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }}] ~ } - \bar "|" - { g2 r2 } - \bar "|" - { r1 } - \bar "|" - { r16[ fis8.^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }}] ~ fis2. } - \bar "|" - { g4^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }} ~ g8[ g8^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }}] ~ g2 } - \bar "|" - { fis2^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} fis2^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }} ~ } - \bar "|" - { fis8.[ g16^\markup { \pad-markup #0.2 "+29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }}] ~ g2. ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g2 ~ g16[ r8.] r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/490b1e6e_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/490b1e6e_code.scd deleted file mode 100644 index 3eb3cbd..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/490b1e6e_code.scd +++ /dev/null @@ -1,1058 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \".." +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - -~transcribe.value(~seq, dir); - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, attack, release = 1, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = rrand(20, 40); - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - //sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * amp * EnvGen.kr(Env.adsr(attack, 0.3, 0.9, release, 0.9, -3), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); - //Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.sine(dur), gate, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs; - - sigs = [~stringModelBusArray, ~sineBusArray/*, ~bassBusArray, ~hdustBusArray, ~samplerBusArray*/].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -/* -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -*/ -mixer = Synth.tail(~group, \mixer); - -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -/* -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -*/ -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/490b1e6e_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/490b1e6e_mus_model.json deleted file mode 100644 index 64ab1de..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/490b1e6e_mus_model.json +++ /dev/null @@ -1,63 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ -2, 0, 0, 1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 1.375 ], - [ [ [ -2, 0, 0, 1, 1, 1 ], [ -2, 0, 0, 1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 0.875 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 0, 0, 1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 0.875 ], - [ [ [ -2, 0, 0, 1, 2, 0 ], [ -2, 0, 0, 1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 0.75 ], - [ [ [ -1, 0, 0, 1, 0, 0 ], [ -2, 0, 0, 1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 1.5 ], - [ [ [ -1, -1, 0, 1, 1, 0 ], [ -2, 0, 0, 1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 1.125 ], - [ [ [ -2, 0, 1, 1, 1, 0 ], [ -2, 0, 0, 1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 1.625 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ -2, 0, 0, 1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 1.625 ] - ], - [ - [ [ [ -1, 0, 0, 0, 1, 0 ], [ -2, 0, 0, 1, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ "Rest" ] ], 0 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ -2, 0, 0, 1, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 1.25 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ -1, -1, 1, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 1.125 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 0, -2, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 1 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ -2, 1, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 0.5 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ -1, 0, -1, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 1.625 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, -1 ], [ 0, -1, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 2 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 0, -1, 0, -1, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 1.75 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ -1, -1, 1, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 1.5 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 0, -2, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 1.25 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 0, -2, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ "Rest" ] ], 0.875 ], - [ [ [ "Rest" ], [ 0, -2, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ 0, -2, 0, 0, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.375 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 0, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ] -], -"cur_uid": "490b1e6e", -"ref_uid": "nil", -"order_seed": 209164, -"dur_seed": 417909, -"motifs_seed": 885208, -"entrances_probs_vals": [ 0.34, 0, 10, 0.5, 2, 0, 0.5, 0.24509803921569, 0.89189189189189, 0.5, 1, 0.5, 0.5, 0.8562091503268, 0.69932432432432, 1, 0.5 ], -"passages_probs_vals": [ 0.34, 0, 10, 0.5, 2, 0, 0.5, 0.24509803921569, 0.89189189189189, 0.5, 1, 0.5, 0.5, 0.8562091503268, 0.69932432432432, 1, 0.5 ], -"exits_probs_vals": [ 0.34, 0, 10, 0.5, 2, 0, 0.5, 0.24509803921569, 0.89189189189189, 0.5, 1, 0.5, 0.5, 0.8562091503268, 0.69932432432432, 1, 0.5 ], -"ranges": [ [ -1200, 2400 ], [ -1200, 2400 ], [ -1200, 2400 ], [ -1200, 2400 ] ], -"step_probs_vals": [ 0, 1200, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 2 ], [ 0, 0, 0, 0 ], [ 1, 3 ] ] -], -"sus_weights": [ 0.75, 0.75, 0.75 ], -"order_size": [ 1, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "true", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/lilypond/part_I.ly deleted file mode 100644 index 57e7dcf..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/lilypond/part_I.ly +++ /dev/null @@ -1,26 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2. r8[ fis'8^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'2. ~ fis'8[ r8] } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/lilypond/part_II.ly deleted file mode 100644 index 72acd78..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/lilypond/part_II.ly +++ /dev/null @@ -1,26 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2. r8[ ais8^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais4 ~ ais16[ r8.] r2 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/lilypond/part_III.ly deleted file mode 100644 index c698c38..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/lilypond/part_III.ly +++ /dev/null @@ -1,26 +0,0 @@ -{ - { dis1^\markup { \pad-markup #0.2 "+20"} ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis2 d2^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }} ~ } - \bar "|" - { d16[ dis8.^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }}] ~ dis4 ~ dis16[ cis8.^\markup { \pad-markup #0.2 "-47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ cis16[ d8.^\markup { \pad-markup #0.2 "-35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}] ~ } - \bar "|" - { d2 ~ d8[ d8^\markup { \pad-markup #0.2 "+9"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↓" }}] ~ d4 ~ } - \bar "|" - { d2 ~ d8[ cis8^\markup { \pad-markup #0.2 "-19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }}] ~ cis4 ~ } - \bar "|" - { cis2 d2^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }} ~ } - \bar "|" - { d4 dis2.^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }} ~ } - \bar "|" - { dis4 ~ dis16[ r8.] r2 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/lilypond/part_IV.ly deleted file mode 100644 index 72aea57..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/490b1e6e/lilypond/part_IV.ly +++ /dev/null @@ -1,26 +0,0 @@ -{ - { r2 r8.[ c'16^\markup { \pad-markup #0.2 "-39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }}] ~ c'4 ~ } - \bar "|" - { c'8[ ais8^\markup { \pad-markup #0.2 "+22"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }}] ~ ais4 ~ ais16[ a8.^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↑" }}] ~ a8.[ ais16^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↓" }}] ~ } - \bar "|" - { ais2 ~ ais8.[ gis16^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }}] ~ gis4 ~ } - \bar "|" - { gis4 g2.^\markup { \pad-markup #0.2 "+6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }} ~ } - \bar "|" - { g16[ fis8.^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }}] ~ fis2. ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis4 ~ fis16[ r8.] r2 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/4a8a6e53_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/4a8a6e53_code.scd deleted file mode 100644 index 3eb3cbd..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/4a8a6e53_code.scd +++ /dev/null @@ -1,1058 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \".." +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - -~transcribe.value(~seq, dir); - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, attack, release = 1, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = rrand(20, 40); - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - //sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * amp * EnvGen.kr(Env.adsr(attack, 0.3, 0.9, release, 0.9, -3), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); - //Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.sine(dur), gate, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs; - - sigs = [~stringModelBusArray, ~sineBusArray/*, ~bassBusArray, ~hdustBusArray, ~samplerBusArray*/].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -/* -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -*/ -mixer = Synth.tail(~group, \mixer); - -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -/* -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -*/ -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/4a8a6e53_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/4a8a6e53_mus_model.json deleted file mode 100644 index 150baf5..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/4a8a6e53_mus_model.json +++ /dev/null @@ -1,97 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 1.5 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 1.25 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 1 ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 1.25 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0.75 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ], [ "Rest" ] ], 1.5 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ "Rest" ] ], 1.25 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ "Rest" ] ], 1.375 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ "Rest" ] ], 0.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ "Rest" ] ], 0.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ "Rest" ] ], 0.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 0, 1 ], [ "Rest" ] ], 1.125 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ] ], 1.25 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ "Rest" ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ] ], 0.875 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, -1, 0, -1, 0 ] ], 0.875 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, -1, 0, -1, 0 ] ], 0.75 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 1, -1, 0 ], [ 1, 0, -1, 0, -1, 0 ] ], 1.5 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 1, -1, 0 ], [ 0, 0, 0, 0, -1, 1 ] ], 1.25 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 1, -1, 0 ], [ 0, 1, 0, 0, -1, 0 ] ], 0.625 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 1, 0, 0, -1, 0 ] ], 0.625 ], - [ [ [ 0, 0, 1, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 1, 0, 0, -1, 0 ] ], 0.625 ], - [ [ [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 1, 0, 0, -1, 0 ] ], 1.375 ], - [ [ [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 1, 0, -1, 0 ] ], 1.375 ], - [ [ [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 2, 0, 0, -1, -1, 0 ], [ 0, 0, 1, 0, -1, 0 ] ], 1.5 ], - [ [ [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 2, 0, 0, 0, -1, -1 ], [ 0, 0, 1, 0, -1, 0 ] ], 0.75 ], - [ [ [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 2, 0, 0, 0, -1, -1 ], [ 1, -1, 0, 0, -1, 0 ] ], 1 ] - ], - [ - [ [ [ 1, 0, 0, -1, -1, 0 ], [ "Rest" ], [ 2, 0, 0, 0, -1, -1 ], [ 1, -1, 0, 0, -1, 0 ] ], 0.75 ], - [ [ [ 0, -1, 0, 1, -1, 0 ], [ "Rest" ], [ 2, 0, 0, 0, -1, -1 ], [ 1, -1, 0, 0, -1, 0 ] ], 1 ], - [ [ [ 0, -1, 0, 1, -1, 0 ], [ "Rest" ], [ 2, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 0.875 ], - [ [ [ 0, -1, 0, 0, -1, 1 ], [ "Rest" ], [ 2, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 1.25 ], - [ [ [ 0, -1, 0, 0, -1, 1 ], [ "Rest" ], [ 1, -1, 0, 1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 1.125 ], - [ [ [ 1, -1, -1, 0, -1, 0 ], [ "Rest" ], [ 1, -1, 0, 1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 1 ], - [ [ [ 1, -1, -1, 0, -1, 0 ], [ "Rest" ], [ 1, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 0.75 ], - [ [ [ 1, -1, -1, 0, -1, 0 ], [ "Rest" ], [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 0.625 ], - [ [ [ 0, -1, 0, 0, 0, 0 ], [ "Rest" ], [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 0.75 ], - [ [ [ 1, -1, 0, 0, -2, 0 ], [ "Rest" ], [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 1.375 ], - [ [ [ 1, -1, 0, 0, -2, 0 ], [ "Rest" ], [ 2, -2, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 0.875 ], - [ [ [ 0, -1, 0, 0, -1, 1 ], [ "Rest" ], [ 2, -2, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 3.375 ], - [ [ [ 0, -1, 0, 0, -1, 1 ], [ "Rest" ], [ 2, -2, 0, 0, -1, 0 ], [ "Rest" ] ], 1.5 ], - [ [ [ 0, -1, 0, 0, -1, 1 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.375 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 2 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 1, 0, -1 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, -2 ] ], - [ [ 0, 0, 0, 1, 0, -1 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, 0, 0, -1 ], [ -1, 0, 0, 1, 0, -1 ] ], - [ [ 0, 0, 0, 1, 0, -1 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, 0, 0, -1 ], [ 0, 0, 0, 0, -1, 0 ] ], - [ [ 0, 0, 0, 1, 0, -1 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ] ], - [ [ 1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ] ] -], -"cur_uid": "4a8a6e53", -"ref_uid": "nil", -"order_seed": 320463, -"dur_seed": 903977, -"motifs_seed": 895384, -"entrances_probs_vals": [ 0.75, 0, 10, 0, 0.5, 0.26424870466321, 0.75675675675676, 0.5, 0.5, 0.58549222797927, 0.72635135135135, 1, 0.5 ], -"passages_probs_vals": [ 0.75, 0, 10, 0, 0.5, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0.75, 0, 10, 0, 0.5, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ -384, 2400 ], [ -507, 2400 ], [ -282, 2237 ], [ -1200, 2053 ] ], -"step_probs_vals": [ 0, 1200, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 1 ], [ 0, 3, 2, 3, 3, 2 ], [ ] ], - [ [ 2, 1 ], [ 3, 0, 3 ], [ ] ], - [ [ 1 ], [ 3, 2, 0 ], [ ] ] -], -"sus_weights": [ 0.75, 0.69, 0.75 ], -"order_size": [ 2, 6 ], -"passages_size": [ 0, 10 ], -"motif_edited": "true", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/lilypond/part_I.ly deleted file mode 100644 index e9e6601..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/lilypond/part_I.ly +++ /dev/null @@ -1,56 +0,0 @@ -{ - { r2. e'4^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }} ~ } - \bar "|" - { e'2 e'4^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ e'8.[ f'16^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ } - \bar "|" - { f'4 ~ f'8[ g'8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ g'4 ~ g'8[ ais'8^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ } - \bar "|" - { ais'4 ~ ais'8[ c''8^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ c''2 } - \bar "|" - { gis'4^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }} ~ gis'8.[ gis'16^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}] ~ gis'4 ~ gis'8[ f'8^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ } - \bar "|" - { f'2 e'4^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ e'8[ r8] } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2 r16[ dis'8.^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }}] ~ dis'4 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'8[ dis'8^\markup { \pad-markup #0.2 "-11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }}] ~ dis'2 d'4^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'4 ~ d'8[ ais8^\markup { \pad-markup #0.2 "+35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}] ~ ais2 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais8.[ b16^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }}] ~ b2. ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b2 ~ b16[ r8.] r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/lilypond/part_II.ly deleted file mode 100644 index 3c00ff8..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/lilypond/part_II.ly +++ /dev/null @@ -1,56 +0,0 @@ -{ - { c'1^\markup { \pad-markup #0.2 "+0"} ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'4 ~ c'16[ e'8.^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ e'2 ~ } - \bar "|" - { e'2 ~ e'8.[ g'16^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ g'4 ~ } - \bar "|" - { g'4 ~ g'8[ ais'8^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ ais'2 ~ } - \bar "|" - { ais'4 ~ ais'8.[ gis'16^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }}] ~ gis'2 } - \bar "|" - { gis'2^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ gis'8[ g'8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ g'4 ~ } - \bar "|" - { g'8[ f'8^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ f'2. ~ } - \bar "|" - { f'4 ~ f'8[ e'8^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }}] ~ e'2 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'16[ fis'8.^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ fis'2. ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'16[ a'8.^\markup { \pad-markup #0.2 "-20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ a'2 ~ a'16[ ais'8.^\markup { \pad-markup #0.2 "+8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↓" }}] ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'2 ~ ais'16[ b'8.^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ b'4 ~ } - \bar "|" - { b'2 ~ b'8[ a'8^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }}] ~ a'4 ~ } - \bar "|" - { a'2 ~ a'8.[ fis'16^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}] ~ fis'4 ~ } - \bar "|" - { fis'16[ f'8.^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }}] ~ f'2. ~ } - \bar "|" - { f'4 ~ f'8.[ e'16^\markup { \pad-markup #0.2 "+45"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }}] ~ e'2 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'4 ~ e'16[ r8.] r2 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/lilypond/part_III.ly deleted file mode 100644 index 75dcb1c..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/lilypond/part_III.ly +++ /dev/null @@ -1,56 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r16[ ais8.^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ ais2. ~ } - \bar "|" - { ais2. gis4^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { gis16[ fis8.^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }}] ~ fis2. ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis2 ~ fis8.[ r16] r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/lilypond/part_IV.ly deleted file mode 100644 index 41471e8..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4a8a6e53/lilypond/part_IV.ly +++ /dev/null @@ -1,56 +0,0 @@ -{ - { r4 r8.[ c'16^\markup { \pad-markup #0.2 "+0"}] ~ c'2 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 } - \bar "|" - { b1^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b4 ~ b8[ ais8^\markup { \pad-markup #0.2 "+35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}] ~ ais8.[ a16^\markup { \pad-markup #0.2 "-20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }}] ~ a4 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a16[ a8.^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }}] ~ a2. } - \bar "|" - { gis1^\markup { \pad-markup #0.2 "-13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }} ~ } - \bar "|" - { gis8.[ gis16^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }}] ~ gis2. ~ } - \bar "|" - { gis4 ~ gis8[ f8^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ f4 fis4^\markup { \pad-markup #0.2 "-5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }} ~ } - \bar "|" - { fis2. ~ fis8[ gis8^\markup { \pad-markup #0.2 "-13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }}] ~ } - \bar "|" - { gis1 ~ } - \bar "|" - { gis1 ~ } - \bar "|" - { gis1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/4b7745df_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/4b7745df_code.scd deleted file mode 100644 index a98b916..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/4b7745df_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/4b7745df_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/4b7745df_mus_model.json deleted file mode 100644 index f30b098..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/4b7745df_mus_model.json +++ /dev/null @@ -1,48 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 7.5 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 3.625 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ 3, -2, -1, -1, 1, 0 ] ], 1.875 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ 3, -2, -1, -1, 1, 0 ] ], 1.75 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ 3, -1, 0, -2, 1, 0 ] ], 3.375 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ "Rest" ], [ 2, -1, -1, -1, 1, 0 ], [ 3, -1, 0, -2, 1, 0 ] ], 1.75 ], - [ [ [ "Rest" ], [ "Rest" ], [ 2, -1, -1, -1, 1, 0 ], [ 3, -1, 0, -2, 1, 0 ] ], 0.75 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 3, -1, 0, -2, 1, 0 ] ], 1.125 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 4.25 ] - ] - ] -], -"last_changes": -[ - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 3, -2, 0, -1, 1, -1 ], [ 3, -2, 0, -1, 0, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 3, -2, 0, -1, 1, -1 ], [ 2, -1, 0, -1, 1, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 3, -2, 0, -1, 1, -1 ], [ 3, -2, -1, -1, 1, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ 3, -2, -1, -1, 1, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ 3, -1, 0, -2, 1, 0 ] ] -], -"cur_uid": "4b7745df", -"ref_uid": "7d3c9a80", -"order_seed": 216475, -"dur_seed": 241788, -"motifs_seed": 440693, -"entrances_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -3600, -312 ], [ -1872, 1378 ], [ -145, 1583 ], [ -182, 1527 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.082304526748971, 0.99431818181818, 0.14197530864198, 0, 1, 0 ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 1, 0 ], [ 3, 2, 3 ], [ ] ] -], -"sus_weights": [ 0, 0.65, 0 ], -"order_size": [ 1, 2 ], -"passages_size": [ 1, 6 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/lilypond/part_I.ly deleted file mode 100644 index d9ec1f9..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/lilypond/part_I.ly +++ /dev/null @@ -1,28 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2 r16[ d''8.^\markup { \pad-markup #0.2 "-8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }}] ~ d''4 ~ } - \bar "|" - { d''1 ~ } - \bar "|" - { d''4 ~ d''8[ dis''8^\markup { \pad-markup #0.2 "+12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}] ~ dis''2 ~ } - \bar "|" - { dis''1 ~ } - \bar "|" - { dis''1 ~ } - \bar "|" - { dis''2. ~ dis''8[ r8] } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/lilypond/part_II.ly deleted file mode 100644 index 6118a4a..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/lilypond/part_II.ly +++ /dev/null @@ -1,28 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2 a'2^\markup { \pad-markup #0.2 "-6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'4 ~ a'16[ r8.] r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/lilypond/part_III.ly deleted file mode 100644 index 80764d9..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/lilypond/part_III.ly +++ /dev/null @@ -1,28 +0,0 @@ -{ - { fis'1^\markup { \pad-markup #0.2 "-21"} ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'16[ r8.] r2. } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/lilypond/part_IV.ly deleted file mode 100644 index 8cc8f1d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4b7745df/lilypond/part_IV.ly +++ /dev/null @@ -1,28 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2. cis'4^\markup { \pad-markup #0.2 "-19"} ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'2. ~ cis'8.[ r16] } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/4e7d35e5_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/4e7d35e5_code.scd deleted file mode 100644 index a98b916..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/4e7d35e5_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/4e7d35e5_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/4e7d35e5_mus_model.json deleted file mode 100644 index 0eebea8..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/4e7d35e5_mus_model.json +++ /dev/null @@ -1,52 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 1, 0, 1, -2, 1, 1 ] ], 1.75 ], - [ [ [ "Rest" ], [ "Rest" ], [ 1, 0, 0, -2, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], 1.5 ] - ], - [ - [ [ [ "Rest" ], [ "Rest" ], [ 1, 0, 0, -2, 1, 1 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ 1, -1, 1, -2, 2, 0 ], [ 1, 0, 0, -2, 1, 1 ], [ "Rest" ] ], 1.5 ], - [ [ [ "Rest" ], [ 1, -1, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 2, 0 ], [ "Rest" ] ], 0 ], - [ [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 2, 0 ], [ "Rest" ] ], 0.75 ], - [ [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 3, 0 ], [ "Rest" ] ], 1.375 ], - [ [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ "Rest" ], [ "Rest" ] ], 1.125 ], - [ [ [ 0, -1, 1, -2, 2, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0.625 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3.375 ] - ] - ] -], -"last_changes": -[ - [ [ 1, -1, 1, -3, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 0, 1, 1, -2, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ 1, -1, 1, -3, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, 0, 0, -2, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ 1, -1, 1, -3, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 3, 0 ], [ 1, 0, 1, -2, 1, 1 ] ] -], -"cur_uid": "4e7d35e5", -"ref_uid": "6d635e88", -"order_seed": 516056, -"dur_seed": 358555, -"motifs_seed": 595740, -"entrances_probs_vals": [ 0.18, 0.28, 1.4285714285714, 0.47, 1.62, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0.29, 0, 1.1111111111111, 0.65934065934066, 1.37, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0.18, 0.28, 1.4285714285714, 0.47, 1.62, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2411.1455108359, -850.77399380805 ], [ -1872, 450 ], [ -479, 1304.0247678019 ], [ -368, 1173.9938080495 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.082304526748971, 0.99431818181818, 0.33950617283951, 0, 0.72839506172839, 0, 1, 0 ], -"passages_weights": [ 0.35, 0.42, 0.75, 0.9, 0.93 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 3 ], [ 2 ], [ 0, 1 ] ], - [ [ 1 ], [ 2, 0, 2 ], [ 3 ] ] -], -"sus_weights": [ 0.41, 0, 0 ], -"order_size": [ 2, 6 ], -"passages_size": [ 0, 5 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/lilypond/part_I.ly deleted file mode 100644 index 18a5337..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/lilypond/part_I.ly +++ /dev/null @@ -1,14 +0,0 @@ -{ - { ais'1^\markup { \pad-markup #0.2 "+41"} ~ } - \bar "|" - { ais'2 ~ ais'8[ r8] r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/lilypond/part_II.ly deleted file mode 100644 index 0674392..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/lilypond/part_II.ly +++ /dev/null @@ -1,14 +0,0 @@ -{ - { r2. r8[ g'8^\markup { \pad-markup #0.2 "-46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }}] ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'4 ~ g'8[ gis'8^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }}] ~ gis'4 fis'4^\markup { \pad-markup #0.2 "+1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }} ~ } - \bar "|" - { fis'4 ~ fis'8.[ r16] r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/lilypond/part_III.ly deleted file mode 100644 index 7778860..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/lilypond/part_III.ly +++ /dev/null @@ -1,14 +0,0 @@ -{ - { r1 } - \bar "|" - { r2 r8[ c'8^\markup { \pad-markup #0.2 "+49"}] ~ c'4 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/lilypond/part_IV.ly deleted file mode 100644 index 0f106c9..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/4e7d35e5/lilypond/part_IV.ly +++ /dev/null @@ -1,14 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r4 r8[ c8^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ c2 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c4 ~ c16[ r8.] r2 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/52c9a980_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/52c9a980_code.scd deleted file mode 100644 index a98b916..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/52c9a980_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/52c9a980_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/52c9a980_mus_model.json deleted file mode 100644 index f3cde46..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/52c9a980_mus_model.json +++ /dev/null @@ -1,55 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 1, 0, 1, -2, 1, 1 ] ], 2 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 1, -1, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], 1.5 ] - ], - [ - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 1, -1, 1, 1 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ 1, -1, 1, -2, 2, 0 ], [ 0, 0, 1, -1, 1, 1 ], [ "Rest" ] ], 1.5 ], - [ [ [ "Rest" ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -1, 1, -2, 1, 0 ], [ "Rest" ] ], 0 ], - [ [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -1, 1, -2, 1, 0 ], [ "Rest" ] ], 0.75 ], - [ [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ "Rest" ] ], 0.75 ], - [ [ [ -1, -1, 1, -1, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ "Rest" ] ], 0.625 ], - [ [ [ 0, -1, 0, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ "Rest" ] ], 1.25 ], - [ [ [ 0, -1, 0, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -1, 1, -2, 2, -1 ], [ "Rest" ] ], 2.25 ], - [ [ [ 0, -1, 0, -2, 2, 0 ], [ "Rest" ], [ 2, -1, 1, -2, 2, -1 ], [ "Rest" ] ], 1.5 ], - [ [ [ 0, -1, 0, -2, 2, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0.875 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3.0 ] - ] - ] -], -"last_changes": -[ - [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -1, 1, -2, 1, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ -1, -1, 1, -1, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ 0, -1, 0, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ 0, -1, 0, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -1, 1, -2, 2, -1 ], [ 1, 0, 1, -2, 1, 1 ] ] -], -"cur_uid": "52c9a980", -"ref_uid": "6d635e88", -"order_seed": 516056, -"dur_seed": 358555, -"motifs_seed": 210544, -"entrances_probs_vals": [ 0.18, 0.28, 1.4285714285714, 0.82, 2.0054945054945, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0.29, 0, 1.1111111111111, 0.65934065934066, 1.37, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0.18, 0.28, 1.4285714285714, 0.82, 2.0054945054945, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2411.1455108359, -850.77399380805 ], [ -1872, 450 ], [ -479, 1304.0247678019 ], [ -368, 1173.9938080495 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.082304526748971, 0.99431818181818, 0.33950617283951, 0, 0.72839506172839, 0, 1, 0 ], -"passages_weights": [ 0.35, 0.42, 0.75, 0.9, 0.93 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 3 ], [ 2 ], [ 0, 1 ] ], - [ [ 1 ], [ 2, 0, 2, 0, 0, 2 ], [ 3 ] ] -], -"sus_weights": [ 0.41, 0, 0 ], -"order_size": [ 2, 6 ], -"passages_size": [ 0, 5 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/lilypond/part_I.ly deleted file mode 100644 index ba446df..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/lilypond/part_I.ly +++ /dev/null @@ -1,18 +0,0 @@ -{ - { ais'1^\markup { \pad-markup #0.2 "+41"} ~ } - \bar "|" - { ais'2. r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/lilypond/part_II.ly deleted file mode 100644 index 75eeb2b..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/lilypond/part_II.ly +++ /dev/null @@ -1,18 +0,0 @@ -{ - { r1 } - \bar "|" - { gis'1^\markup { \pad-markup #0.2 "+9"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }} ~ } - \bar "|" - { gis'2 g'4^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↓" }} ~ g'8[ f'8^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'8.[ e'16^\markup { \pad-markup #0.2 "+9"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↓" }}] ~ e'2. ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'16[ r8.] r2. } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/lilypond/part_III.ly deleted file mode 100644 index 9e681f0..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/lilypond/part_III.ly +++ /dev/null @@ -1,18 +0,0 @@ -{ - { r1 } - \bar "|" - { r2. c'4^\markup { \pad-markup #0.2 "+49"} ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'4 ~ c'16[ r8.] r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/lilypond/part_IV.ly deleted file mode 100644 index bb5c589..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/52c9a980/lilypond/part_IV.ly +++ /dev/null @@ -1,18 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2 c2^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { c4 ais,4^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }} ~ ais,16[ a,8.^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }}] ~ a,4 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,2 r2 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/5e54c468_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/5e54c468_code.scd deleted file mode 100644 index 3eb3cbd..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/5e54c468_code.scd +++ /dev/null @@ -1,1058 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \".." +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - -~transcribe.value(~seq, dir); - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, attack, release = 1, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = rrand(20, 40); - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - //sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * amp * EnvGen.kr(Env.adsr(attack, 0.3, 0.9, release, 0.9, -3), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); - //Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.sine(dur), gate, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs; - - sigs = [~stringModelBusArray, ~sineBusArray/*, ~bassBusArray, ~hdustBusArray, ~samplerBusArray*/].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -/* -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -*/ -mixer = Synth.tail(~group, \mixer); - -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -/* -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -*/ -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/5e54c468_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/5e54c468_mus_model.json deleted file mode 100644 index f3f6493..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/5e54c468_mus_model.json +++ /dev/null @@ -1,70 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 1, -1, 0, -1, 1, -1 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 1, -1 ], [ "Rest" ] ], 0.625 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 1, -1 ], [ "Rest" ] ], 2.5 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 1, -1 ], [ 2, -1, -1, -1, 1, 0 ] ], 1 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 1, -1 ], [ 2, -1, 1, -1, 1, -1 ] ], 3.875 ] - ], - [ - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ 2, -1, 1, -1, 1, -1 ] ], 2 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -1, 0, -1, 1, -1 ], [ "Rest" ], [ 2, -1, 1, -1, 1, -1 ] ], 6.5 ] - ], - [ - [ [ [ "Rest" ], [ 2, -1, 0, -1, 1, -1 ], [ "Rest" ], [ 2, -1, 1, -1, 1, -1 ] ], 0 ], - [ [ [ "Rest" ], [ 2, -1, 0, -1, 1, -1 ], [ "Rest" ], [ "Rest" ] ], 0.75 ], - [ [ [ "Rest" ], [ 2, -1, 0, -1, 1, -1 ], [ 2, -1, 0, 0, 1, -1 ], [ "Rest" ] ], 1.125 ], - [ [ [ "Rest" ], [ 2, -1, 0, -1, 1, -1 ], [ 2, -1, 0, -1, 1, 0 ], [ "Rest" ] ], 4.5 ] - ], - [ - [ [ [ "Rest" ], [ 2, -1, 0, -1, 1, -1 ], [ 2, -1, 0, -1, 1, 0 ], [ 2, -1, 1, -1, 1, -1 ] ], 0.875 ], - [ [ [ "Rest" ], [ 2, -1, 0, -2, 1, 0 ], [ 2, -1, 0, -1, 1, 0 ], [ 2, -1, 1, -1, 1, -1 ] ], 1.25 ], - [ [ [ "Rest" ], [ 1, 0, 1, -1, 1, -1 ], [ 2, -1, 0, -1, 1, 0 ], [ 2, -1, 1, -1, 1, -1 ] ], 3.75 ] - ], - [ - [ [ [ "Rest" ], [ 1, -1, 1, -1, 1, 0 ], [ 2, -1, 0, -1, 1, 0 ], [ 2, -1, 1, -1, 1, -1 ] ], 1 ], - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, 0, -1, 1, 0 ], [ 2, -1, 1, -1, 1, -1 ] ], 3.75 ], - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, 0, -1, 1, 0 ], [ "Rest" ] ], 2 ], - [ [ [ "Rest" ], [ "Rest" ], [ 2, -1, 0, -1, 1, 0 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 4.5 ] - ] - ] -], -"last_changes": -[ - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -1, 0, -1, 1, -1 ], [ 2, -1, 0, -1, 1, 0 ], [ 2, -1, 1, -1, 1, -1 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -1, 0, -2, 1, 0 ], [ 2, -1, 0, -1, 1, 0 ], [ 2, -1, 1, -1, 1, -1 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 1, 0, 1, -1, 1, -1 ], [ 2, -1, 0, -1, 1, 0 ], [ 2, -1, 1, -1, 1, -1 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 1, -1, 1, -1, 1, 0 ], [ 2, -1, 0, -1, 1, 0 ], [ 2, -1, 1, -1, 1, -1 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, 0, -1, 1, 0 ], [ 2, -1, 1, -1, 1, -1 ] ] -], -"cur_uid": "5e54c468", -"ref_uid": "6fb60ab6", -"order_seed": 499586, -"dur_seed": 134526, -"motifs_seed": 636998, -"entrances_probs_vals": [ 0.34, 0.99, 3.1746031746032, 0.5, 2, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0.34, 1.5873015873016, 4.7222222222222, 0.5, 2.1153846153846, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0.34, 0.32, 1.9444444444444, 0.5, 2.12, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -3600, -312.07430340557 ], [ -1872, 1378.3281733746 ], [ -144.89164086687, 1582.6625386997 ], [ -182.04334365325, 1527 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.082304526748971, 0.99431818181818, 0.14197530864198, 0, 1, 0 ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 2, 1, 0 ], [ 3, 3 ], [ ] ], - [ [ 3, 0 ], [ 1 ], [ 2 ] ], - [ [ 1 ], [ 2, 2 ], [ 0, 3 ] ], - [ [ 3, 2 ], [ 1, 1 ], [ 0 ] ], - [ [ 3, 2 ], [ 1, 1 ], [ 0 ] ] -], -"sus_weights": [ 0.75, 0.25, 0.25 ], -"order_size": [ 3, 6 ], -"passages_size": [ 0, 3 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/lilypond/part_I.ly deleted file mode 100644 index 98ddfc8..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/lilypond/part_I.ly +++ /dev/null @@ -1,44 +0,0 @@ -{ - { r1 } - \bar "|" - { r2 r16[ a'8.^\markup { \pad-markup #0.2 "-6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}] ~ a'4 ~ } - \bar "|" - { a'16[ gis'8.^\markup { \pad-markup #0.2 "+26"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }}] ~ gis'2. ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'4 r2. } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r4 r8.[ gis'16^\markup { \pad-markup #0.2 "+26"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}] ~ gis'2 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'2. r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/lilypond/part_II.ly deleted file mode 100644 index 6b51d38..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/lilypond/part_II.ly +++ /dev/null @@ -1,44 +0,0 @@ -{ - { e1^\markup { \pad-markup #0.2 "+40"} ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2 r8[ d''8^\markup { \pad-markup #0.2 "+9"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }}] ~ d''4 ~ } - \bar "|" - { d''8.[ cis''16^\markup { \pad-markup #0.2 "-19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }}] ~ cis''2. ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''2. r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/lilypond/part_III.ly deleted file mode 100644 index 2632120..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/lilypond/part_III.ly +++ /dev/null @@ -1,44 +0,0 @@ -{ - { fis'1^\markup { \pad-markup #0.2 "-21"} ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 } - \bar "|" - { e'1^\markup { \pad-markup #0.2 "+40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }} ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'2. ~ e'8[ dis'8^\markup { \pad-markup #0.2 "+12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }}] ~ } - \bar "|" - { dis'2 dis'2^\markup { \pad-markup #0.2 "+28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }} ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'4 ~ dis'8[ f'8^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }}] ~ f'4 ~ f'8[ fis'8^\markup { \pad-markup #0.2 "-21"}] ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'2. r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/lilypond/part_IV.ly deleted file mode 100644 index 1f3a4d8..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/5e54c468/lilypond/part_IV.ly +++ /dev/null @@ -1,44 +0,0 @@ -{ - { r4 r16[ cis'8.^\markup { \pad-markup #0.2 "-19"}] ~ cis'2 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'4 r2. } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/61ce9067_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/61ce9067_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/61ce9067_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/61ce9067_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/61ce9067_mus_model.json deleted file mode 100644 index bdc8f6f..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/61ce9067_mus_model.json +++ /dev/null @@ -1,55 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, -1, 1, -2, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0.125 ], - [ [ [ 0, -1, 1, -2, 1, 0 ], [ 2, -1, 1, -3, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 0.75 ], - [ [ [ 0, -1, 1, -2, 1, 0 ], [ 2, -1, 1, -3, 1, 0 ], [ 3, -2, 1, -2, 1, 0 ], [ "Rest" ] ], 0.75 ], - [ [ [ 0, -1, 1, -2, 1, 0 ], [ 2, -1, 1, -3, 1, 0 ], [ 3, -2, 1, -2, 1, 0 ], [ 3, -1, 1, -3, 1, 0 ] ], 0.375 ], - [ [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 1, 0 ], [ 3, -2, 1, -2, 1, 0 ], [ 3, -1, 1, -3, 1, 0 ] ], 1 ], - [ [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -1, 1, 0 ], [ 3, -1, 1, -3, 1, 0 ] ], 0.5 ], - [ [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -1, 1, 0 ], [ 2, -1, 1, -2, 1, 0 ] ], 0.75 ], - [ [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 2, -2, 1, 0 ], [ 1, -1, 1, -1, 1, 0 ], [ 2, -1, 1, -2, 1, 0 ] ], 1.125 ], - [ [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 2, -2, 1, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -1, 1, -2, 1, 0 ] ], 0.75 ], - [ [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 2, -2, 1, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -1, 2, -2, 1, 0 ] ], 0.25 ], - [ [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -1, 2, -2, 1, 0 ] ], 0.875 ], - [ [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 1, 1 ], [ 2, -1, 2, -2, 1, 0 ] ], 0.875 ], - [ [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 1, 1 ], [ 2, -1, 1, -2, 1, 0 ] ], 0.375 ], - [ [ [ "Rest" ], [ 1, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 1, 1 ], [ 2, -1, 1, -2, 1, 0 ] ], 0.375 ], - [ [ [ "Rest" ], [ 1, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 1, 1 ], [ "Rest" ] ], 0.375 ], - [ [ [ "Rest" ], [ 1, -1, 1, -2, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 0.125 ] - ] - ] -], -"last_changes": -[ - [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 2, -2, 1, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -1, 1, -2, 1, 0 ] ], - [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 2, -2, 1, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -1, 2, -2, 1, 0 ] ], - [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -1, 2, -2, 1, 0 ] ], - [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 1, 1 ], [ 2, -1, 2, -2, 1, 0 ] ], - [ [ 0, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 1, 1 ], [ 2, -1, 1, -2, 1, 0 ] ] -], -"cur_uid": "61ce9067", -"ref_uid": "4200a90d", -"order_seed": 278192, -"dur_seed": 660041, -"motifs_seed": 150685, -"entrances_probs_vals": [ 0, 0, 0, 0.19, 0.93406593406593, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0.2, 2.3015873015873, 0.08, 1.2912087912088, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0.16, 1.0714285714286, 0.16, 1.510989010989, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2411.1455108359, -850.77399380805 ], [ -1872, 450 ], [ -479, 1304.0247678019 ], [ -368, 1173.9938080495 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.08641975308642, 0.9375, 0.50617283950617, 0.89772727272727, 0.69135802469136, 0, 1, 0 ], -"passages_weights": [ 0.27, 0, 0.6, 0, 1 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3 ], [ ] ] -], -"sus_weights": [ 0.62, 0.25, 0 ], -"order_size": [ 7, 10 ], -"passages_size": [ 0, 6 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/lilypond/part_I.ly deleted file mode 100644 index 36d5c00..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/lilypond/part_I.ly +++ /dev/null @@ -1,10 +0,0 @@ -{ - { r2. r16[ a'8.^\markup { \pad-markup #0.2 "+29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ } - \bar "|" - { a'2. g'4^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'16[ b'8.^\markup { \pad-markup #0.2 "-16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ b'2.} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/lilypond/part_II.ly deleted file mode 100644 index 172d34d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/lilypond/part_II.ly +++ /dev/null @@ -1,10 +0,0 @@ -{ - { r4 r8.[ c''16^\markup { \pad-markup #0.2 "-4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ c''2 ~ } - \bar "|" - { c''2 f'2^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }} ~ } - \bar "|" - { f'2 ~ f'8.[ c'16^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }}] ~ c'4 ~ } - \bar "|" - { c'2 ~ c'8[ dis'8^\markup { \pad-markup #0.2 "+39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }}] ~ dis'4} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/lilypond/part_III.ly deleted file mode 100644 index 80195eb..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/lilypond/part_III.ly +++ /dev/null @@ -1,10 +0,0 @@ -{ - { r16[ a8.^\markup { \pad-markup #0.2 "+29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}] ~ a2. } - \bar "|" - { g1^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { g8[ b8^\markup { \pad-markup #0.2 "-16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ b2. ~ } - \bar "|" - { b8.[ g16^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ g2.} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/lilypond/part_IV.ly deleted file mode 100644 index ce0c70d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/61ce9067/lilypond/part_IV.ly +++ /dev/null @@ -1,10 +0,0 @@ -{ - { g,1^\markup { \pad-markup #0.2 "-2"} ~ } - \bar "|" - { g,1 ~ } - \bar "|" - { g,1 ~ } - \bar "|" - { g,1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/62820081/62820081_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/62820081/62820081_code.scd deleted file mode 100644 index a98b916..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/62820081/62820081_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/62820081/62820081_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/62820081/62820081_mus_model.json deleted file mode 100644 index ab5d8c3..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/62820081/62820081_mus_model.json +++ /dev/null @@ -1,48 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 1.5 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 4.375 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ 1, -1, 0, 0, 1, 0 ] ], 1.625 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ 1, -1, 0, 0, 1, 0 ] ], 1.25 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 3.375 ], - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 1.625 ], - [ [ [ "Rest" ], [ "Rest" ], [ 2, -1, -1, -1, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 1.625 ], - [ [ [ "Rest" ], [ "Rest" ], [ 2, -1, -1, -1, 1, 0 ], [ "Rest" ] ], 0.875 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 10.0 ] - ] - ] -], -"last_changes": -[ - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, 0, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, 0, 0, -1, 1, 0 ], [ 3, -2, 0, -1, 1, -1 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, 0, 0, -1, 1, 0 ], [ 1, -1, 0, 0, 1, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ 1, -1, 0, 0, 1, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ] -], -"cur_uid": "62820081", -"ref_uid": "79e0a4a7", -"order_seed": 216475, -"dur_seed": 914627, -"motifs_seed": 252655, -"entrances_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -3600, -312 ], [ -1872, 1378 ], [ -145, 1583 ], [ -182, 1527 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.082304526748971, 0.99431818181818, 0.14197530864198, 0, 1, 0 ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 1, 0 ], [ 3, 2, 3 ], [ ] ] -], -"sus_weights": [ 0, 0.65, 0 ], -"order_size": [ 1, 1 ], -"passages_size": [ 1, 6 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/631e2af1/631e2af1_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/631e2af1/631e2af1_code.scd deleted file mode 100644 index 8e9fe42..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/631e2af1/631e2af1_code.scd +++ /dev/null @@ -1,943 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/631e2af1/631e2af1_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/631e2af1/631e2af1_mus_model.json deleted file mode 100644 index 78ae751..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/631e2af1/631e2af1_mus_model.json +++ /dev/null @@ -1,48 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 1.125 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 4.375 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ 1, -1, 0, 0, 1, 0 ] ], 1.375 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 2, 0 ], [ 1, -1, 0, 0, 1, 0 ] ], 1.25 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 2, 0 ], [ 2, -2, 0, -1, 2, 0 ] ], 2.375 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 2, 0 ], [ "Rest" ] ], 1.75 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 1.125 ], - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 1.625 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 5.0 ] - ] - ] -], -"last_changes": -[ - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, 0, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, 0, 0, -1, 1, 0 ], [ 3, -2, 0, -1, 1, -1 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, 0, 0, -1, 1, 0 ], [ 1, -1, 0, 0, 1, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 2, 0 ], [ 1, -1, 0, 0, 1, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 2, 0 ], [ 2, -2, 0, -1, 2, 0 ] ] -], -"cur_uid": "631e2af1", -"ref_uid": "79e0a4a7", -"order_seed": 216475, -"dur_seed": 698877, -"motifs_seed": 336611, -"entrances_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -3600, -312 ], [ -1872, 1378 ], [ -145, 1583 ], [ -182, 1527 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.082304526748971, 0.99431818181818, 0.14197530864198, 0, 1, 0 ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 1, 0 ], [ 3, 2, 3 ], [ ] ] -], -"sus_weights": [ 0, 0.65, 0 ], -"order_size": [ 1, 1 ], -"passages_size": [ 1, 6 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/66f6a618_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/66f6a618_code.scd deleted file mode 100644 index 3eb3cbd..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/66f6a618_code.scd +++ /dev/null @@ -1,1058 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \".." +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - -~transcribe.value(~seq, dir); - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, attack, release = 1, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = rrand(20, 40); - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - //sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * amp * EnvGen.kr(Env.adsr(attack, 0.3, 0.9, release, 0.9, -3), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); - //Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.sine(dur), gate, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs; - - sigs = [~stringModelBusArray, ~sineBusArray/*, ~bassBusArray, ~hdustBusArray, ~samplerBusArray*/].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -/* -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -*/ -mixer = Synth.tail(~group, \mixer); - -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -/* -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -*/ -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/66f6a618_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/66f6a618_mus_model.json deleted file mode 100644 index fe45ed4..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/66f6a618_mus_model.json +++ /dev/null @@ -1,91 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 1, -1, 0, 0, -1, 0 ] ], 0.75 ], - [ [ [ "Rest" ], [ 1, -1, 0, 0, -1, 0 ], [ "Rest" ], [ 1, -1, 0, 0, -1, 0 ] ], 0.5 ], - [ [ [ "Rest" ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 1.375 ], - [ [ [ 0, -1, 0, 0, -1, 1 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 1.5 ], - [ [ [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 0.875 ], - [ [ [ 1, -2, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 0.75 ], - [ [ [ 0, -1, 1, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 0.75 ], - [ [ [ 1, -1, 0, -1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 8.75 ] - ], - [ - [ [ [ 1, -1, 0, -1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 2, -1, 0, -1, -1, 0 ] ], 0.625 ], - [ [ [ 1, -1, 0, -1, -1, 0 ], [ 0, -1, 0, 1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 2, -1, 0, -1, -1, 0 ] ], 0.625 ], - [ [ [ 0, -1, 0, 0, -1, 0 ], [ 0, -1, 0, 1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 2, -1, 0, -1, -1, 0 ] ], 0.75 ], - [ [ [ 1, -1, 0, 0, -1, -1 ], [ 0, -1, 0, 1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 2, -1, 0, -1, -1, 0 ] ], 0.875 ], - [ [ [ 1, -1, 0, 0, -1, -1 ], [ 0, -1, 0, 1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 2, -1, 0, 0, -1, -1 ] ], 1.25 ], - [ [ [ 1, -1, 0, 0, -1, -1 ], [ 1, -1, -1, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 2, -1, 0, 0, -1, -1 ] ], 1.75 ], - [ [ [ 1, -1, 0, 0, -1, -1 ], [ 1, -1, -1, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 1, -1, 0, 0, -1, -1 ], [ 0, -1, 0, 0, -1, 1 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, -1, 1, 0, -1, 0 ], [ 0, -1, 0, 0, -1, 1 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 1.875 ], - [ [ [ 0, -1, 1, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 3 ] - ], - [ - [ [ [ 0, -1, -1, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 0, -1, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, -1, 0, -1, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 1.625 ], - [ [ [ -1, -1, 0, 0, 0, 1 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 0.875 ], - [ [ [ 0, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 1.25 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 4.625 ] - ], - [ - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 2, -1, -1, 0, -1, 0 ] ], 1.75 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 2, 0, 0, -1, -1, 0 ] ], 1.875 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, 0, -1, 0, 0, 0 ] ], 0.625 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, 0, 0, 0, -1, 0 ] ], 0.625 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 7.25 ] - ], - [ - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 1.875 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 1, -1, -1, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 1.625 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, -2, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 1.625 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 1, -2, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 1 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, -1 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 3.75 ] - ], - [ - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, -1 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 0 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, -1 ], [ "Rest" ], [ 0, 0, 0, 0, 1, 0 ] ], 1.25 ], - [ [ [ "Rest" ], [ -2, 0, 0, 0, 1, 1 ], [ "Rest" ], [ 0, 0, 0, 0, 1, 0 ] ], 1.875 ], - [ [ [ "Rest" ], [ -2, 1, 0, 0, 1, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 1, 0 ] ], 1.25 ], - [ [ [ "Rest" ], [ -1, 0, -1, 0, 1, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 1, 0 ] ], 2 ], - [ [ [ "Rest" ], [ -2, 0, 0, 1, 1, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 1, 0 ] ], 2.625 ], - [ [ [ "Rest" ], [ -2, 0, 0, 1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 0.25 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0.375 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 0, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ] -], -"cur_uid": "66f6a618", -"ref_uid": "nil", -"order_seed": 209164, -"dur_seed": 417909, -"motifs_seed": 885208, -"entrances_probs_vals": [ 0.34, 0, 10, 0.5, 2, 0, 0.5, 0.24509803921569, 0.89189189189189, 0.5, 1, 0.5, 0.5, 0.8562091503268, 0.69932432432432, 1, 0.5 ], -"passages_probs_vals": [ 0.34, 0, 10, 0.5, 2, 0, 0.5, 0.24509803921569, 0.89189189189189, 0.5, 1, 0.5, 0.5, 0.8562091503268, 0.69932432432432, 1, 0.5 ], -"exits_probs_vals": [ 0.34, 0, 10, 0.5, 2, 0, 0.5, 0.24509803921569, 0.89189189189189, 0.5, 1, 0.5, 0.5, 0.8562091503268, 0.69932432432432, 1, 0.5 ], -"ranges": [ [ -1200, 2400 ], [ -1200, 2400 ], [ -1200, 2400 ], [ -1200, 2400 ] ], -"step_probs_vals": [ 0, 1200, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 2 ], [ 0, 0, 0, 0 ], [ 1, 3 ] ] -], -"sus_weights": [ 0.75, 0.75, 0.75 ], -"order_size": [ 1, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "true", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/lilypond/part_I.ly deleted file mode 100644 index d05522a..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/lilypond/part_I.ly +++ /dev/null @@ -1,70 +0,0 @@ -{ - { b1^\markup { \pad-markup #0.2 "+47"} ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b2 ~ b8[ d'8^\markup { \pad-markup #0.2 "-22"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ d'4 ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'16[ dis'8.^\markup { \pad-markup #0.2 "+6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ dis'2. ~ } - \bar "|" - { dis'2 ~ dis'16[ f'8.^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↑" }}] ~ f'4 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'8.[ gis'16^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }}] ~ gis'2. ~ } - \bar "|" - { gis'16[ a'8.^\markup { \pad-markup #0.2 "-20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }}] ~ a'2. } - \bar "|" - { gis'4^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ gis'16[ fis'8.^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ fis'8[ fis'8^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }}] ~ fis'4 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'2 ~ fis'8.[ r16] r4} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/lilypond/part_II.ly deleted file mode 100644 index 602b0d6..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/lilypond/part_II.ly +++ /dev/null @@ -1,70 +0,0 @@ -{ - { r2 r8[ b8^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ b4 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b8.[ r16] r2. } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/lilypond/part_III.ly deleted file mode 100644 index 6d06a75..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/lilypond/part_III.ly +++ /dev/null @@ -1,70 +0,0 @@ -{ - { r4 r8[ b8^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ b2 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b2. ~ b8.[ a16^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}] ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a2 ~ a8.[ gis16^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }}] ~ gis4 ~ } - \bar "|" - { gis2 ~ gis16[ gis8.^\markup { \pad-markup #0.2 "-13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }}] ~ gis4 ~ } - \bar "|" - { gis2 fis2^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }} ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis4 f2.^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { f8.[ gis16^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }}] ~ gis2. } - \bar "|" - { fis2.^\markup { \pad-markup #0.2 "-5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↓" }} ~ fis16[ e8.^\markup { \pad-markup #0.2 "+45"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }}] ~ } - \bar "|" - { e4 ~ e16[ e8.^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ e2 ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e2. ~ e16[ d8.^\markup { \pad-markup #0.2 "-8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }}] ~ } - \bar "|" - { d2. cis4^\markup { \pad-markup #0.2 "-47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }} ~ } - \bar "|" - { cis4 ~ cis8[ d8^\markup { \pad-markup #0.2 "-35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }}] ~ d2 ~ } - \bar "|" - { d4 ~ d8[ dis8^\markup { \pad-markup #0.2 "+20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }}] ~ dis2 ~ } - \bar "|" - { dis2. ~ dis16[ r8.]} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/lilypond/part_IV.ly deleted file mode 100644 index bc81ade..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/66f6a618/lilypond/part_IV.ly +++ /dev/null @@ -1,70 +0,0 @@ -{ - { r1 } - \bar "|" - { r4 r16[ gis8.^\markup { \pad-markup #0.2 "-13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }}] ~ gis2 ~ } - \bar "|" - { gis16[ fis8.^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }}] ~ fis4 e4^\markup { \pad-markup #0.2 "+45"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ e8[ dis8^\markup { \pad-markup #0.2 "+33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}] ~ } - \bar "|" - { dis4 d2.^\markup { \pad-markup #0.2 "-22"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }} ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d4 b,4^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ b,8[ dis8^\markup { \pad-markup #0.2 "+6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↓" }}] ~ dis4 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis2 ~ dis16[ dis8.^\markup { \pad-markup #0.2 "+33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }}] ~ dis4 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 } - \bar "|" - { cis2^\markup { \pad-markup #0.2 "+12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }} dis2^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }} } - \bar "|" - { d2.^\markup { \pad-markup #0.2 "-22"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }} ~ d16[ cis8.^\markup { \pad-markup #0.2 "+39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }}] ~ } - \bar "|" - { cis4 b,2^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ b,8[ c8^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↑" }}] ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c8.[ r16] r2. } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/6d635e88_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/6d635e88_code.scd deleted file mode 100644 index a98b916..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/6d635e88_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/6d635e88_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/6d635e88_mus_model.json deleted file mode 100644 index 228456c..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/6d635e88_mus_model.json +++ /dev/null @@ -1,95 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 1, -2, 1, -2, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.625 ], - [ [ [ 1, -2, 1, -2, 1, 0 ], [ "Rest" ], [ 2, -1, 1, -2, 1, 0 ], [ "Rest" ] ], 3.125 ], - [ [ [ 1, -2, 1, -2, 1, 0 ], [ 3, -2, 1, -2, 0, 0 ], [ 2, -1, 1, -2, 1, 0 ], [ "Rest" ] ], 1.125 ], - [ [ [ 1, -2, 1, -2, 1, 0 ], [ 3, -2, 0, -2, 1, 0 ], [ 2, -1, 1, -2, 1, 0 ], [ "Rest" ] ], 3.5 ] - ], - [ - [ [ [ 1, -2, 1, -2, 1, 0 ], [ 3, -2, 0, -2, 1, 0 ], [ 2, -1, 1, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 3.25 ], - [ [ [ 1, -2, 1, -2, 1, 0 ], [ 1, -2, 1, -1, 1, 1 ], [ 2, -1, 1, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 1.375 ], - [ [ [ 1, -2, 1, -2, 1, 0 ], [ 1, -1, 1, -1, 1, 0 ], [ 2, -1, 1, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 2.75 ] - ], - [ - [ [ [ 1, -2, 1, -2, 1, 0 ], [ 3, -2, 1, -2, 1, -1 ], [ 2, -1, 1, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 1.875 ], - [ [ [ 1, -2, 1, -2, 1, 0 ], [ 1, 0, 1, -2, 1, 0 ], [ 2, -1, 1, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 2.875 ] - ], - [ - [ [ [ "Rest" ], [ 1, 0, 1, -2, 1, 0 ], [ 2, -1, 1, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 2 ], - [ [ [ "Rest" ], [ 1, -2, 1, -1, 2, 0 ], [ 2, -1, 1, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 3.125 ] - ], - [ - [ [ [ "Rest" ], [ "Rest" ], [ 2, -1, 1, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 1.25 ], - [ [ [ 0, 0, 1, -2, 1, 0 ], [ "Rest" ], [ 2, -1, 1, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 3.875 ] - ], - [ - [ [ [ 0, 0, 1, -2, 1, 0 ], [ 1, -2, 1, -1, 2, 0 ], [ 2, -1, 1, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 1.875 ], - [ [ [ 0, 0, 1, -2, 1, 0 ], [ 1, -2, 1, -1, 2, 0 ], [ 1, 0, 1, -2, 2, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 2 ], - [ [ [ 0, 0, 1, -2, 1, 0 ], [ 1, -2, 1, -1, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 2.75 ] - ], - [ - [ [ [ 0, 0, 1, -2, 1, 0 ], [ 1, -2, 1, -1, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ 1, 0, 1, -1, 1, 0 ] ], 1.875 ], - [ [ [ 0, 0, 1, -2, 1, 0 ], [ 1, -2, 1, -1, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], 2.875 ] - ], - [ - [ [ [ 0, 0, 1, -2, 1, 0 ], [ 2, -2, 0, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], 1.25 ], - [ [ [ 0, 0, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], 3.25 ] - ], - [ - [ [ [ 0, 0, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 0, 1, 1, -2, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], 1.125 ], - [ [ [ 0, -1, 1, -2, 1, 1 ], [ 1, -1, 1, -2, 2, 0 ], [ 0, 1, 1, -2, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], 2 ], - [ [ [ -1, 1, 1, -2, 1, 1 ], [ 1, -1, 1, -2, 2, 0 ], [ 0, 1, 1, -2, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], 4 ] - ], - [ - [ [ [ -1, 0, 1, -2, 2, 1 ], [ 1, -1, 1, -2, 2, 0 ], [ 0, 1, 1, -2, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], 1.875 ], - [ [ [ 1, -1, 1, -3, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 0, 1, 1, -2, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], 2.25 ], - [ [ [ 1, -1, 1, -3, 2, 0 ], [ "Rest" ], [ 0, 1, 1, -2, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], 1.75 ], - [ [ [ 1, -1, 1, -3, 2, 0 ], [ "Rest" ], [ "Rest" ], [ 1, 0, 1, -2, 1, 1 ] ], 1.75 ], - [ [ [ 1, -1, 1, -3, 2, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.625 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 4.0 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 1, -2, 1, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 0, 1, 1, -2, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ 0, -1, 1, -2, 1, 1 ], [ 1, -1, 1, -2, 2, 0 ], [ 0, 1, 1, -2, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ -1, 1, 1, -2, 1, 1 ], [ 1, -1, 1, -2, 2, 0 ], [ 0, 1, 1, -2, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ -1, 0, 1, -2, 2, 1 ], [ 1, -1, 1, -2, 2, 0 ], [ 0, 1, 1, -2, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ 1, -1, 1, -3, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 0, 1, 1, -2, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ] -], -"cur_uid": "6d635e88", -"ref_uid": "6ed95c4c", -"order_seed": 526896, -"dur_seed": 815251, -"motifs_seed": 342685, -"entrances_probs_vals": [ 0, 0.91269841269841, 2.8571428571429, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0.63, 2.1031746031746, 0.98901098901099, 2.23, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0.91269841269841, 2.8571428571429, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2894.1176470588, -312 ], [ -1872, 1378 ], [ -145, 1583 ], [ -182, 1527 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.082304526748971, 0.99431818181818, 0.23045267489712, 1.1102230246252e-16, 0.61522633744856, 0, 1, 0 ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.8 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0, 2 ], [ 1, 1 ], [ 3 ] ], - [ [ 0, 2, 3 ], [ 1, 1 ], [ ] ], - [ [ 2, 0, 3 ], [ 1, 1 ], [ ] ], - [ [ 2, 3 ], [ 1 ], [ 0 ] ], - [ [ 3, 2 ], [ 0 ], [ 1 ] ], - [ [ 1, 3, 0 ], [ 2, 2 ], [ ] ], - [ [ 0, 2, 1 ], [ 3, 3 ], [ ] ], - [ [ 2, 0, 3 ], [ 1, 1 ], [ ] ], - [ [ 3, 1 ], [ 2, 0, 0 ], [ ] ], - [ [ 2, 3, 1 ], [ 0, 0 ], [ ] ] -], -"sus_weights": [ 0, 0.31, 0.55 ], -"order_size": [ 10, 10 ], -"passages_size": [ 0, 2 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/lilypond/part_I.ly deleted file mode 100644 index ea663b7..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/lilypond/part_I.ly +++ /dev/null @@ -1,70 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2 r8.[ ais'16^\markup { \pad-markup #0.2 "-35"}] ~ ais'4 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'8.[ c''16^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ c''2. ~ } - \bar "|" - { c''8[ ais'8^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }}] ~ ais'2. ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'8.[ r16] r2. } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/lilypond/part_II.ly deleted file mode 100644 index 8850de9..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/lilypond/part_II.ly +++ /dev/null @@ -1,70 +0,0 @@ -{ - { r2. r16[ g'8.^\markup { \pad-markup #0.2 "-2"}] ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'2. ~ g'16[ gis'8.^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }}] ~ } - \bar "|" - { gis'2. ~ gis'16[ f'8.^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }}] ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'2. ~ f'16[ f'8.^\markup { \pad-markup #0.2 "+42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}] ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'4 ~ f'16[ r8.] r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/lilypond/part_III.ly deleted file mode 100644 index 710041c..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/lilypond/part_III.ly +++ /dev/null @@ -1,70 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r4 r8[ fis'8^\markup { \pad-markup #0.2 "+45"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }}] ~ fis'4 ~ fis'8.[ gis'16^\markup { \pad-markup #0.2 "+10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}] ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'4 ~ gis'16[ fis'8.^\markup { \pad-markup #0.2 "+5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }}] ~ fis'2 } - \bar "|" - { f'1^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }} ~ } - \bar "|" - { f'4 ~ f'8[ e'8^\markup { \pad-markup #0.2 "-44"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ e'2 ~ } - \bar "|" - { e'4 ~ e'16[ d'8.^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }}] ~ d'2 ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'2. dis'4^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }} ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'4 ~ dis'16[ r8.] r2 } - \bar "|" - { r1 } - \bar "|" - { r2. r8[ dis'8^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }}] ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'2 ~ dis'16[ d'8.^\markup { \pad-markup #0.2 "-39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }}] ~ d'4 ~ } - \bar "|" - { d'8.[ c'16^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }}] ~ c'2. ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'4 ~ c'8.[ r16] r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/lilypond/part_IV.ly deleted file mode 100644 index 8163bc3..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/6d635e88/lilypond/part_IV.ly +++ /dev/null @@ -1,70 +0,0 @@ -{ - { c1^\markup { \pad-markup #0.2 "-4"} ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c2. r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2. r8.[ d16^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }}] ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d4 ~ d8[ dis8^\markup { \pad-markup #0.2 "+39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }}] ~ dis2 ~ } - \bar "|" - { dis4 ~ dis8[ f8^\markup { \pad-markup #0.2 "+42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ f2 ~ } - \bar "|" - { f1 ~ } - \bar "|" - { f4 ~ f8[ e8^\markup { \pad-markup #0.2 "-8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }}] ~ e2 ~ } - \bar "|" - { e4 ~ e16[ dis8.^\markup { \pad-markup #0.2 "-19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }}] ~ dis2 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/6ed95c4c_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/6ed95c4c_code.scd deleted file mode 100644 index a98b916..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/6ed95c4c_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/6ed95c4c_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/6ed95c4c_mus_model.json deleted file mode 100644 index c03359a..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/6ed95c4c_mus_model.json +++ /dev/null @@ -1,66 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 4.125 ], - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ 2, -2, 0, -1, 1, 1 ] ], 1.375 ], - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ 3, -2, 0, -2, 1, 0 ], [ 2, -2, 0, -1, 1, 1 ] ], 1.25 ], - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ 3, -2, 0, -2, 1, 0 ], [ 2, -1, 0, -1, 1, 0 ] ], 1.125 ], - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ], [ 2, -1, 0, -1, 1, 0 ] ], 3.5 ] - ], - [ - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ], [ "Rest" ] ], 1.5 ], - [ [ [ 1, -3, 1, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ], [ "Rest" ] ], 1.625 ], - [ [ [ 1, -3, 1, -1, 1, 0 ], [ 1, -2, 1, -1, 1, 1 ], [ 2, -2, 1, -1, 1, 0 ], [ "Rest" ] ], 2.25 ], - [ [ [ 1, -3, 1, -1, 1, 0 ], [ 1, -1, 1, -1, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ], [ "Rest" ] ], 1.5 ], - [ [ [ 0, -2, 2, -1, 1, 0 ], [ 1, -1, 1, -1, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ], [ "Rest" ] ], 2.125 ], - [ [ [ 1, -2, 1, -2, 1, 0 ], [ 1, -1, 1, -1, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ], [ "Rest" ] ], 4.25 ] - ], - [ - [ [ [ 1, -2, 1, -2, 1, 0 ], [ 1, -1, 1, -1, 1, 0 ], [ 3, -2, 0, -2, 1, 0 ], [ "Rest" ] ], 2 ], - [ [ [ 1, -2, 1, -2, 1, 0 ], [ 3, -2, 1, -2, 1, -1 ], [ 3, -2, 0, -2, 1, 0 ], [ "Rest" ] ], 1.75 ], - [ [ [ 1, -2, 1, -2, 1, 0 ], [ 3, -2, 1, -2, 1, -1 ], [ 3, -2, 0, -2, 1, 0 ], [ 3, -2, 1, -2, 1, 0 ] ], 1 ], - [ [ [ 1, -2, 1, -2, 1, 0 ], [ 3, -2, 1, -2, 1, -1 ], [ 3, -2, 0, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 1.125 ], - [ [ [ 1, -2, 1, -2, 1, 0 ], [ 2, -2, 2, -2, 1, 0 ], [ 3, -2, 0, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 1.75 ], - [ [ [ 1, -2, 1, -2, 1, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ 3, -2, 0, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 2 ], - [ [ [ 1, -2, 1, -2, 1, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ 2, -1, 1, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 3.625 ], - [ [ [ 1, -2, 1, -2, 1, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ "Rest" ], [ 2, -2, 1, -1, 1, 0 ] ], 1 ], - [ [ [ 1, -2, 1, -2, 1, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 0.875 ], - [ [ [ "Rest" ], [ 3, -3, 1, -2, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 0.25 ] - ] - ] -], -"last_changes": -[ - [ [ 1, -2, 1, -2, 1, 0 ], [ 3, -2, 1, -2, 1, -1 ], [ 3, -2, 0, -2, 1, 0 ], [ 3, -2, 1, -2, 1, 0 ] ], - [ [ 1, -2, 1, -2, 1, 0 ], [ 3, -2, 1, -2, 1, -1 ], [ 3, -2, 0, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], - [ [ 1, -2, 1, -2, 1, 0 ], [ 2, -2, 2, -2, 1, 0 ], [ 3, -2, 0, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], - [ [ 1, -2, 1, -2, 1, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ 3, -2, 0, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], - [ [ 1, -2, 1, -2, 1, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ 2, -1, 1, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ] -], -"cur_uid": "6ed95c4c", -"ref_uid": "4b7745df", -"order_seed": 602538, -"dur_seed": 495773, -"motifs_seed": 128841, -"entrances_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 1.55, 3.452380952381, 0.98901098901099, 2.23, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2894.1176470588, -312 ], [ -1872, 1378 ], [ -145, 1583 ], [ -182, 1527 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.082304526748971, 0.99431818181818, 0.14197530864198, 0, 1, 0 ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.8 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 1 ], [ 3, 2, 3, 2 ], [ 0 ] ], - [ [ 2 ], [ 0, 1, 1, 0, 0 ], [ 3 ] ], - [ [ 0 ], [ 2, 1, 3, 3, 1, 1, 2 ], [ ] ] -], -"sus_weights": [ 0.66, 0, 0 ], -"order_size": [ 1, 4 ], -"passages_size": [ 2, 5 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/lilypond/part_I.ly deleted file mode 100644 index 4ccdb1e..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/lilypond/part_I.ly +++ /dev/null @@ -1,42 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r16[ d''8.^\markup { \pad-markup #0.2 "+19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }}] ~ d''2. ~ } - \bar "|" - { d''4 ~ d''8[ cis''8^\markup { \pad-markup #0.2 "-19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }}] ~ cis''2 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''2 ~ cis''8.[ r16] r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r8.[ c''16^\markup { \pad-markup #0.2 "-4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ c''4 ~ c''8.[ ais'16^\markup { \pad-markup #0.2 "-35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ ais'4 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'4 ~ ais'8.[ r16] r2 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/lilypond/part_II.ly deleted file mode 100644 index dba1611..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/lilypond/part_II.ly +++ /dev/null @@ -1,42 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2. gis'4^\markup { \pad-markup #0.2 "+10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }} ~ } - \bar "|" - { gis'2. ~ gis'8.[ ais'16^\markup { \pad-markup #0.2 "-35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}] ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'4 ~ ais'16[ gis'8.^\markup { \pad-markup #0.2 "+10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}] ~ gis'2 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'8[ g'8^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ g'2. ~ } - \bar "|" - { g'2. ~ g'8.[ r16] } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/lilypond/part_III.ly deleted file mode 100644 index ce5e5ba..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/lilypond/part_III.ly +++ /dev/null @@ -1,42 +0,0 @@ -{ - { fis'1^\markup { \pad-markup #0.2 "-21"} ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'4 fis'2.^\markup { \pad-markup #0.2 "+5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }} ~ } - \bar "|" - { fis'4 ~ fis'8[ f'8^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }}] ~ f'2 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'4 ~ f'16[ e'8.^\markup { \pad-markup #0.2 "-44"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ e'2 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'4 e'2.^\markup { \pad-markup #0.2 "-18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { e'8[ f'8^\markup { \pad-markup #0.2 "-6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ f'2. ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/lilypond/part_IV.ly deleted file mode 100644 index 18babdb..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/6ed95c4c/lilypond/part_IV.ly +++ /dev/null @@ -1,42 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r4 r8.[ dis16^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }}] ~ dis2 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis8[ d8^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }}] ~ d2. ~ } - \bar "|" - { d8.[ c16^\markup { \pad-markup #0.2 "-4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }}] ~ c2. ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c2. ~ c8[ r8]} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/6fb60ab6_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/6fb60ab6_code.scd deleted file mode 100644 index 3eb3cbd..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/6fb60ab6_code.scd +++ /dev/null @@ -1,1058 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \".." +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - -~transcribe.value(~seq, dir); - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, attack, release = 1, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = rrand(20, 40); - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - //sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * amp * EnvGen.kr(Env.adsr(attack, 0.3, 0.9, release, 0.9, -3), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); - //Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.sine(dur), gate, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs; - - sigs = [~stringModelBusArray, ~sineBusArray/*, ~bassBusArray, ~hdustBusArray, ~samplerBusArray*/].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -/* -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -*/ -mixer = Synth.tail(~group, \mixer); - -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -/* -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -*/ -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/6fb60ab6_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/6fb60ab6_mus_model.json deleted file mode 100644 index 1778bf5..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/6fb60ab6_mus_model.json +++ /dev/null @@ -1,56 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 1, -1, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0.625 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ 1, 0, 0, -1, 1, 0 ] ], 0 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ "Rest" ], [ 2, -1, 0, -1, 1, -1 ], [ 1, 0, 0, -1, 1, 0 ] ], 1.75 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ "Rest" ], [ 2, -1, 0, -1, 1, -1 ], [ 2, -1, 0, -1, 0, 0 ] ], 1.875 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ "Rest" ], [ 2, -1, 0, -1, 1, -1 ], [ 1, -1, 0, -1, 2, 0 ] ], 1.5 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ "Rest" ], [ 2, -1, 0, -1, 1, -1 ], [ 1, -1, 1, -1, 1, 0 ] ], 0.75 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ "Rest" ], [ 2, -1, 0, -1, 1, -1 ], [ 2, -1, 0, -2, 1, 0 ] ], 1.25 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ "Rest" ], [ 2, -1, 0, -1, 1, -1 ], [ 0, -1, 0, 0, 1, 0 ] ], 1.625 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ "Rest" ], [ 2, -1, 0, -1, 1, -1 ], [ 1, 0, 0, -1, 1, 0 ] ], 1.875 ] - ], - [ - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, 0, -1, 1, -1 ], [ 1, 0, 0, -1, 1, 0 ] ], 1 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 2, 0 ], [ 1, 0, 0, -1, 1, 0 ] ], 1.125 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, 0, -1, -1, 1, 0 ], [ 1, 0, 0, -1, 1, 0 ] ], 0.75 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 1, 0 ] ], 1.5 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -2, 0, -1, 1, 1 ], [ 1, 0, 0, -1, 1, 0 ] ], 1.5 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, 0, 0, -1, 1, -1 ], [ 1, 0, 0, -1, 1, 0 ] ], 1.75 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ 1, 0, 0, -1, 1, 0 ] ], 1.125 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 0.5 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 5.5 ] - ] - ] -], -"last_changes": -[ - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 1, -1 ], [ 1, 0, 0, -1, 1, 0 ] ] -], -"cur_uid": "6fb60ab6", -"ref_uid": "nil", -"order_seed": 209164, -"dur_seed": 417909, -"motifs_seed": 885208, -"entrances_probs_vals": [ 0.34, 0, 10, 0.5, 2, 0, 0.5, 0.24509803921569, 0.89189189189189, 0.5, 1, 0.5, 0.5, 0.8562091503268, 0.69932432432432, 1, 0.5 ], -"passages_probs_vals": [ 0.34, 0, 10, 0.5, 2, 0, 0.5, 0.24509803921569, 0.89189189189189, 0.5, 1, 0.5, 0.5, 0.8562091503268, 0.69932432432432, 1, 0.5 ], -"exits_probs_vals": [ 0.34, 0, 10, 0.5, 2, 0, 0.5, 0.24509803921569, 0.89189189189189, 0.5, 1, 0.5, 0.5, 0.8562091503268, 0.69932432432432, 1, 0.5 ], -"ranges": [ [ -1200, 2400 ], [ -1200, 2400 ], [ -1200, 2400 ], [ -1200, 2400 ] ], -"step_probs_vals": [ 0, 1200, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 2 ], [ 0, 0, 0, 0 ], [ 1, 3 ] ] -], -"sus_weights": [ 0.75, 0.75, 0.75 ], -"order_size": [ 1, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/lilypond/part_I.ly deleted file mode 100644 index 3ed19b7..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/lilypond/part_I.ly +++ /dev/null @@ -1,28 +0,0 @@ -{ - { r4 r16[ gis'8.^\markup { \pad-markup #0.2 "-18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ gis'2 ~ } - \bar "|" - { gis'8.[ g'16^\markup { \pad-markup #0.2 "+29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }}] ~ g'2. ~ } - \bar "|" - { g'8[ fis'8^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }}] ~ fis'2 ~ fis'8[ f'8^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ } - \bar "|" - { f'4 dis'2^\markup { \pad-markup #0.2 "+12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }} ~ dis'8[ ais8^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ } - \bar "|" - { ais2 ~ ais8.[ gis'16^\markup { \pad-markup #0.2 "-18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ gis'4 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/lilypond/part_II.ly deleted file mode 100644 index af38e4d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/lilypond/part_II.ly +++ /dev/null @@ -1,28 +0,0 @@ -{ - { r4 r16[ e'8.^\markup { \pad-markup #0.2 "+40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ e'2 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'8[ fis'8^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }}] ~ fis'4 ~ fis'8.[ e'16^\markup { \pad-markup #0.2 "-4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }}] ~ e'4 ~ } - \bar "|" - { e'16[ d'8.^\markup { \pad-markup #0.2 "+31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }}] ~ d'2 ~ d'16[ d'8.^\markup { \pad-markup #0.2 "+19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }}] ~ } - \bar "|" - { d'2 ~ d'16[ b8.^\markup { \pad-markup #0.2 "+42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↓" }}] ~ b4 ~ } - \bar "|" - { b4 ~ b8.[ r16] r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/lilypond/part_III.ly deleted file mode 100644 index ff528bb..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/lilypond/part_III.ly +++ /dev/null @@ -1,28 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2 r8[ fis'8^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ fis'4 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'4 r2. } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/lilypond/part_IV.ly deleted file mode 100644 index 1592265..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/6fb60ab6/lilypond/part_IV.ly +++ /dev/null @@ -1,28 +0,0 @@ -{ - { cis'1^\markup { \pad-markup #0.2 "-19"} ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'4 r2. } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/761e4585/761e4585_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/761e4585/761e4585_code.scd deleted file mode 100644 index 3eb3cbd..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/761e4585/761e4585_code.scd +++ /dev/null @@ -1,1058 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \".." +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - -~transcribe.value(~seq, dir); - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, attack, release = 1, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = rrand(20, 40); - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - //sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * amp * EnvGen.kr(Env.adsr(attack, 0.3, 0.9, release, 0.9, -3), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); - //Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.sine(dur), gate, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs; - - sigs = [~stringModelBusArray, ~sineBusArray/*, ~bassBusArray, ~hdustBusArray, ~samplerBusArray*/].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -/* -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -*/ -mixer = Synth.tail(~group, \mixer); - -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -/* -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -*/ -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/761e4585/761e4585_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/761e4585/761e4585_mus_model.json deleted file mode 100644 index f2ad529..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/761e4585/761e4585_mus_model.json +++ /dev/null @@ -1,80 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 1, -1, 0, -1, 1, 0 ] ], 1.75 ], - [ [ [ "Rest" ], [ "Rest" ], [ 1, -1, 1, -1, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 0 ], - [ [ [ "Rest" ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -1, 1, -1, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 0.625 ], - [ [ [ "Rest" ], [ 0, -1, 0, 0, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 0.875 ], - [ [ [ "Rest" ], [ 0, -1, 0, 0, 1, 0 ], [ 2, -1, 0, -1, 1, -1 ], [ 1, -1, 0, -1, 1, 0 ] ], 1.375 ], - [ [ [ "Rest" ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -1, 0, -1, 2, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 0 ], - [ [ [ "Rest" ], [ 0, 0, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 2, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 0.5 ], - [ [ [ "Rest" ], [ 0, -1, 0, -1, 1, 1 ], [ 1, -1, 0, -1, 2, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 0 ], - [ [ [ "Rest" ], [ 0, -1, 0, -1, 1, 1 ], [ 1, 0, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 1.25 ], - [ [ [ "Rest" ], [ 0, -1, 0, -1, 1, 1 ], [ 2, -1, -1, -1, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 0 ], - [ [ [ "Rest" ], [ 1, -1, -1, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 1.875 ] - ], - [ - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 1, -1, -1, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 1.625 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ 1, -1, 0, -1, 1, 0 ] ], 0 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ 2, -1, 0, -2, 1, 0 ] ], 0 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 1, -1, 0, -1, 2, 0 ], [ 2, -1, 0, -2, 1, 0 ] ], 1.75 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 2, -1, 0, -2, 1, 0 ] ], 1.75 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 0, -1, 0, -1, 1, 1 ], [ 2, -1, 0, -1, 0, 0 ], [ 2, -1, 0, -2, 1, 0 ] ], 0 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 0, -1, 0, -1, 1, 1 ], [ 1, -1, 0, -1, 1, 1 ], [ 2, -1, 0, -2, 1, 0 ] ], 1.75 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 1, -1, -1, -1, 1, 0 ], [ 1, -1, 0, -1, 1, 1 ], [ 2, -1, 0, -2, 1, 0 ] ], 1.875 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 1, -1, -1, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ 2, -1, 0, -2, 1, 0 ] ], 1.375 ] - ], - [ - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 1, -1, -1, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ "Rest" ] ], 1.375 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 0, 0, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ "Rest" ] ], 1 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -1, -1, -2, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ "Rest" ] ], 1.125 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 1, -1, -1, -1, 2, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ "Rest" ] ], 1.625 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, -1, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ "Rest" ] ], 1.75 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 1, -1, 1, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ "Rest" ] ], 1.125 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ "Rest" ] ], 1.25 ] - ], - [ - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ], [ 2, -1, 0, -2, 1, 0 ] ], 0 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, 0, 1, 0 ], [ 2, -1, 0, -2, 1, 0 ] ], 1.25 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -1, 0, -1, 1, 0 ], [ 2, -1, 0, -2, 1, 0 ] ], 1.25 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 1 ], [ 2, -1, 0, -2, 1, 0 ] ], 1.5 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 3, -1, 0, -2, 1, 0 ], [ 2, -1, 0, -2, 1, 0 ] ], 2.375 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ 2, -1, 0, -2, 1, 0 ] ], 0 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 0, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], - [ [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ] -], -"cur_uid": "761e4585", -"ref_uid": "nil", -"order_seed": 209164, -"dur_seed": 417909, -"motifs_seed": 885208, -"entrances_probs_vals": [ 0.34, 0, 10, 0.5, 2, 0, 0.5, 0.24509803921569, 0.89189189189189, 0.5, 1, 0.5, 0.5, 0.8562091503268, 0.69932432432432, 1, 0.5 ], -"passages_probs_vals": [ 0.34, 0, 10, 0.5, 2, 0, 0.5, 0.24509803921569, 0.89189189189189, 0.5, 1, 0.5, 0.5, 0.8562091503268, 0.69932432432432, 1, 0.5 ], -"exits_probs_vals": [ 0.34, 0, 10, 0.5, 2, 0, 0.5, 0.24509803921569, 0.89189189189189, 0.5, 1, 0.5, 0.5, 0.8562091503268, 0.69932432432432, 1, 0.5 ], -"ranges": [ [ -1200, 2400 ], [ -1200, 2400 ], [ -1200, 2400 ], [ -1200, 2400 ] ], -"step_probs_vals": [ 0, 1200, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 2 ], [ 0, 0, 0, 0 ], [ 1, 3 ] ] -], -"sus_weights": [ 0.75, 0.75, 0.75 ], -"order_size": [ 1, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "true", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/761e4585/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/761e4585/lilypond/part_I.ly deleted file mode 100644 index 8f69c77..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/761e4585/lilypond/part_I.ly +++ /dev/null @@ -1,36 +0,0 @@ -{ - { cis'1^\markup { \pad-markup #0.2 "-19"} ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'2. ~ cis'8.[ dis'16^\markup { \pad-markup #0.2 "+12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}] ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'8.[ r16] r2. } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2. r16[ dis'8.^\markup { \pad-markup #0.2 "+12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}] ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/761e4585/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/761e4585/lilypond/part_II.ly deleted file mode 100644 index af6a6cf..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/761e4585/lilypond/part_II.ly +++ /dev/null @@ -1,36 +0,0 @@ -{ - { r2. r8[ f'8^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }}] ~ } - \bar "|" - { f'8.[ fis'16^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }}] ~ fis'4 ~ fis'8[ e'8^\markup { \pad-markup #0.2 "+40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↓" }}] ~ e'4 ~ } - \bar "|" - { e'4 ~ e'16[ fis'8.^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }}] ~ fis'16[ gis'8.^\markup { \pad-markup #0.2 "-18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}] ~ gis'4 ~ } - \bar "|" - { gis'8.[ a'16^\markup { \pad-markup #0.2 "-6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }}] ~ a'2. ~ } - \bar "|" - { a'2. ~ a'8.[ fis'16^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }}] ~ } - \bar "|" - { fis'2. ~ fis'16[ g'8.^\markup { \pad-markup #0.2 "+29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }}] ~ } - \bar "|" - { g'2 ~ g'8.[ a'16^\markup { \pad-markup #0.2 "+21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ a'4 ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'2 a'2^\markup { \pad-markup #0.2 "-6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'2. ~ a'16[ ais'8.^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ } - \bar "|" - { ais'4 ~ ais'8.[ cis''16^\markup { \pad-markup #0.2 "-19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ cis''2 ~ } - \bar "|" - { cis''16[ d''8.^\markup { \pad-markup #0.2 "+19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }}] ~ d''2 ~ d''16[ dis''8.^\markup { \pad-markup #0.2 "+12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ } - \bar "|" - { dis''1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/761e4585/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/761e4585/lilypond/part_III.ly deleted file mode 100644 index 144d704..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/761e4585/lilypond/part_III.ly +++ /dev/null @@ -1,36 +0,0 @@ -{ - { r2. r8[ ais8^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }}] ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais4 ~ ais16[ gis8.^\markup { \pad-markup #0.2 "-18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}] ~ gis16[ a8.^\markup { \pad-markup #0.2 "+21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }}] ~ a4 ~ } - \bar "|" - { a8.[ a16^\markup { \pad-markup #0.2 "-6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ a2. ~ } - \bar "|" - { a2. ~ a8.[ ais16^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais2 ~ ais8.[ a16^\markup { \pad-markup #0.2 "+21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }}] ~ a4 ~ } - \bar "|" - { a2 ~ a16[ a8.^\markup { \pad-markup #0.2 "-6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}] ~ a4 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a2. ~ a8[ gis8^\markup { \pad-markup #0.2 "-18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ } - \bar "|" - { gis4 ~ gis8[ b8^\markup { \pad-markup #0.2 "+25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }}] ~ b4 ~ b8.[ d'16^\markup { \pad-markup #0.2 "+46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↑" }}] ~ } - \bar "|" - { d'2. d'4^\markup { \pad-markup #0.2 "-8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }} ~ } - \bar "|" - { d'2 ~ d'8[ f'8^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ f'4 ~ } - \bar "|" - { f'8.[ fis'16^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ fis'2. ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/761e4585/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/761e4585/lilypond/part_IV.ly deleted file mode 100644 index 89e838d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/761e4585/lilypond/part_IV.ly +++ /dev/null @@ -1,36 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r8[ cis'8^\markup { \pad-markup #0.2 "-19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ cis'2. ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/774ed940/774ed940_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/774ed940/774ed940_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/774ed940/774ed940_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/774ed940/774ed940_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/774ed940/774ed940_mus_model.json deleted file mode 100644 index beff01e..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/774ed940/774ed940_mus_model.json +++ /dev/null @@ -1,70 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 2, -1, 1, -2, 1, 0 ] ], 0.25 ], - [ [ [ 0, -1, 1, -2, 1, 1 ], [ "Rest" ], [ "Rest" ], [ 2, -1, 1, -2, 1, 0 ] ], 0.5 ], - [ [ [ 0, 0, 1, -2, 1, 0 ], [ "Rest" ], [ "Rest" ], [ 2, -1, 1, -2, 1, 0 ] ], 1.25 ], - [ [ [ 0, -1, 1, -2, 1, 1 ], [ "Rest" ], [ "Rest" ], [ 2, -1, 1, -2, 1, 0 ] ], 0.75 ], - [ [ [ 0, -1, 1, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ 2, -1, 1, -2, 1, 0 ] ], 2.875 ] - ], - [ - [ [ [ 0, -1, 1, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ 0, 0, 1, -1, 1, 0 ] ], 0 ], - [ [ [ 0, -1, 1, -1, 1, 0 ], [ "Rest" ], [ 0, -1, 1, 0, 1, 0 ], [ 0, 0, 1, -1, 1, 0 ] ], 0 ], - [ [ [ 0, -1, 1, -1, 1, 0 ], [ 0, -1, 2, -1, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ], [ 0, 0, 1, -1, 1, 0 ] ], 1.5 ], - [ [ [ 0, -1, 1, -1, 1, 0 ], [ 1, -1, 1, -1, 1, -1 ], [ 0, -1, 1, 0, 1, 0 ], [ 0, 0, 1, -1, 1, 0 ] ], 1.5 ], - [ [ [ 0, -1, 1, -1, 1, 0 ], [ -1, -1, 1, 0, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ], [ 0, 0, 1, -1, 1, 0 ] ], 0 ], - [ [ [ 0, -1, 1, -1, 1, 0 ], [ -1, -1, 1, 0, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ], [ 2, -1, 1, -1, 1, -1 ] ], 1.5 ], - [ [ [ 0, -1, 1, -1, 1, 0 ], [ 0, -1, 1, -1, 2, 0 ], [ 0, -1, 1, 0, 1, 0 ], [ 2, -1, 1, -1, 1, -1 ] ], 0.625 ], - [ [ [ 0, -1, 1, -1, 1, 0 ], [ 1, -2, 1, -1, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ], [ 2, -1, 1, -1, 1, -1 ] ], 1.25 ] - ], - [ - [ [ [ 0, -1, 1, -1, 1, 0 ], [ -1, -1, 1, 0, 1, 1 ], [ 0, -1, 1, 0, 1, 0 ], [ 2, -1, 1, -1, 1, -1 ] ], 0 ], - [ [ [ -2, 0, 1, 0, 1, 0 ], [ -1, -1, 1, 0, 1, 1 ], [ 0, -1, 1, 0, 1, 0 ], [ 2, -1, 1, -1, 1, -1 ] ], 1 ], - [ [ [ -2, 0, 1, 0, 1, 0 ], [ -1, -1, 1, 0, 1, 1 ], [ 0, -1, 1, 0, 1, 0 ], [ 0, -1, 1, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 0, 1, 0, 1, 0 ], [ -1, -1, 1, 1, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ], [ 0, -1, 1, 1, 1, 0 ] ], 1.25 ], - [ [ [ -2, 0, 1, 0, 1, 0 ], [ -1, -1, 2, 0, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ], [ 0, -1, 1, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 0, 1, 0, 1, 0 ], [ -1, -1, 2, 0, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ], [ 0, -1, 1, 0, 2, 0 ] ], 1.125 ], - [ [ [ -2, 0, 1, 0, 1, 0 ], [ -1, -1, 2, 0, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ], [ 1, -1, 1, 0, 1, 0 ] ], 0 ], - [ [ [ -1, -1, 1, 0, 1, 0 ], [ -1, -1, 2, 0, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ], [ 1, -1, 1, 0, 1, 0 ] ], 0.875 ], - [ [ [ -1, -1, 1, 0, 1, 0 ], [ -1, -1, 2, 0, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ], [ 1, -1, 1, 0, 1, 0 ] ], 2 ], - [ [ [ -1, -1, 1, 0, 1, 0 ], [ -1, -1, 2, 0, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ], [ 1, -1, 1, 0, 1, 0 ] ], 0], - [ [ [ -1, -1, 1, 0, 1, 0 ], [ -1, -1, 2, 0, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 2.875 ] - ] - ] -], -"last_changes": -[ - [ [ -2, 0, 1, 0, 1, 0 ], [ -1, -1, 1, 1, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ], [ 0, -1, 1, 1, 1, 0 ] ], - [ [ -2, 0, 1, 0, 1, 0 ], [ -1, -1, 2, 0, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ], [ 0, -1, 1, 1, 1, 0 ] ], - [ [ -2, 0, 1, 0, 1, 0 ], [ -1, -1, 2, 0, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ], [ 0, -1, 1, 0, 2, 0 ] ], - [ [ -2, 0, 1, 0, 1, 0 ], [ -1, -1, 2, 0, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ], [ 1, -1, 1, 0, 1, 0 ] ], - [ [ -1, -1, 1, 0, 1, 0 ], [ -1, -1, 2, 0, 1, 0 ], [ 0, -1, 1, 0, 1, 0 ], [ 1, -1, 1, 0, 1, 0 ] ] -], -"cur_uid": "774ed940", -"ref_uid": "61ce9067", -"order_seed": 473248, -"dur_seed": 979780, -"motifs_seed": 262605, -"entrances_probs_vals": [ 1, 0, 0, 0.19, 1.7582417582418, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0.85, 0, 1.2301587301587, 0.54945054945055, 1.79, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0.16, 1.0714285714286, 0.16, 1.510989010989, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2560, 59.442724458204 ], [ -1074, 393.8080495356 ], [ 59.442724458205, 1638.3900928793 ], [ -52.012383900929, 1582.6625386997 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.092592592592593, 0.78977272727273, 0.16460905349794, 0, 0.24279835390947, 0, 0.60699588477366, 0.63636363636364, 0.73662551440329, 0, 1, 0 ], -"passages_weights": [ 1, 0, 0.6, 0, 0.54 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 3 ], [ 0, 0, 0, 0 ], [ 1, 2 ] ], - [ [ 0 ], [ 3, 2, 1, 1, 1, 3, 1, 1 ], [ ] ], - [ [ 2 ], [ 1, 0, 3, 1, 1, 3, 3, 0 ], [ ] ] -], -"sus_weights": [ 0.69, 0, 0 ], -"order_size": [ 1, 7 ], -"passages_size": [ 3, 6 ], -"motif_edited": "true", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/774ed940/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/774ed940/lilypond/part_I.ly deleted file mode 100644 index 2b16ea6..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/774ed940/lilypond/part_I.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { g'1^\markup { \pad-markup #0.2 "-2"} ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'2. ~ g'16[ c'8.^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'4 ~ c'16[ gis'8.^\markup { \pad-markup #0.2 "+26"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ gis'2 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'2 c''2^\markup { \pad-markup #0.2 "+5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }} ~ } - \bar "|" - { c''8[ gis'8^\markup { \pad-markup #0.2 "-13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↑" }}] ~ gis'4 ~ gis'8.[ d''16^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ d''4 ~ } - \bar "|" - { d''1 ~ } - \bar "|" - { d''8[ r8] r2. } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/774ed940/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/774ed940/lilypond/part_II.ly deleted file mode 100644 index 86115b1..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/774ed940/lilypond/part_II.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2. r16[ d'8.^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'8[ r8] r2. } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/774ed940/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/774ed940/lilypond/part_III.ly deleted file mode 100644 index 9d65346..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/774ed940/lilypond/part_III.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2. r16[ a8.^\markup { \pad-markup #0.2 "-47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ } - \bar "|" - { a2 ~ a16[ gis8.^\markup { \pad-markup #0.2 "+26"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ gis4 ~ } - \bar "|" - { gis4 ~ gis16[ d8.^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ d2 ~ } - \bar "|" - { d16[ ais8.^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }}] ~ ais8[ ais8^\markup { \pad-markup #0.2 "-35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ ais2 } - \bar "|" - { b2^\markup { \pad-markup #0.2 "-24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }} c'2^\markup { \pad-markup #0.2 "+5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { c'8[ fis8^\markup { \pad-markup #0.2 "+22"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }}] ~ fis2. ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis8[ r8] r2. } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/774ed940/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/774ed940/lilypond/part_IV.ly deleted file mode 100644 index c7d9483..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/774ed940/lilypond/part_IV.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { r8[ dis8^\markup { \pad-markup #0.2 "+39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }}] ~ dis8[ d8^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}] ~ d2 } - \bar "|" - { dis4^\markup { \pad-markup #0.2 "+39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }} ~ dis8[ f8^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }}] ~ f2 ~ } - \bar "|" - { f1 ~ } - \bar "|" - { f1 ~ } - \bar "|" - { f1 ~ } - \bar "|" - { f1 } - \bar "|" - { a,1^\markup { \pad-markup #0.2 "+38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }} ~ } - \bar "|" - { a,2 ~ a,8.[ d16^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ d4 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d8[ r8] r2. } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/784130cc/784130cc_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/784130cc/784130cc_code.scd deleted file mode 100644 index a98b916..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/784130cc/784130cc_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/784130cc/784130cc_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/784130cc/784130cc_mus_model.json deleted file mode 100644 index 697284e..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/784130cc/784130cc_mus_model.json +++ /dev/null @@ -1,53 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 1, 0, 1, -2, 1, 1 ] ], 1.75 ], - [ [ [ "Rest" ], [ "Rest" ], [ 1, -1, 1, -2, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], 1.5 ] - ], - [ - [ [ [ "Rest" ], [ "Rest" ], [ 1, -1, 1, -2, 1, 1 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 1, 1 ], [ "Rest" ] ], 1.5 ], - [ [ [ "Rest" ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -1, 1, -2, 2, -1 ], [ "Rest" ] ], 0 ], - [ [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -1, 1, -2, 2, -1 ], [ "Rest" ] ], 0.75 ], - [ [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 2, 0 ], [ "Rest" ] ], 0.75 ], - [ [ [ -1, -1, 1, -2, 2, 1 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 2, 0 ], [ "Rest" ] ], 1.625 ], - [ [ [ -1, -1, 1, -2, 2, 1 ], [ 1, -1, 1, -2, 2, 0 ], [ "Rest" ], [ "Rest" ] ], 1.125 ], - [ [ [ -1, -1, 1, -2, 2, 1 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0.625 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 2.375 ] - ] - ] -], -"last_changes": -[ - [ [ 1, -1, 1, -3, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 1, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ 1, -1, 1, -3, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -1, 1, -2, 2, -1 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -1, 1, -2, 2, -1 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ -1, -1, 1, -2, 2, 1 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ] -], -"cur_uid": "784130cc", -"ref_uid": "6d635e88", -"order_seed": 516056, -"dur_seed": 358555, -"motifs_seed": 830376, -"entrances_probs_vals": [ 0.18, 0.28, 1.4285714285714, 0.47, 1.62, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0.29, 0, 1.1111111111111, 0.65934065934066, 1.37, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0.18, 0.28, 1.4285714285714, 0.47, 1.62, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2411.1455108359, -850.77399380805 ], [ -1872, 450 ], [ -479, 1304.0247678019 ], [ -368, 1173.9938080495 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.082304526748971, 0.99431818181818, 0.33950617283951, 0, 0.72839506172839, 0, 1, 0 ], -"passages_weights": [ 0.35, 0.42, 0.75, 0.9, 0.93 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 3 ], [ 2 ], [ 0, 1 ] ], - [ [ 1 ], [ 2, 0, 2, 0 ], [ 3 ] ] -], -"sus_weights": [ 0.41, 0, 0 ], -"order_size": [ 2, 6 ], -"passages_size": [ 0, 5 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/784130cc/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/784130cc/lilypond/part_I.ly deleted file mode 100644 index 18a5337..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/784130cc/lilypond/part_I.ly +++ /dev/null @@ -1,14 +0,0 @@ -{ - { ais'1^\markup { \pad-markup #0.2 "+41"} ~ } - \bar "|" - { ais'2 ~ ais'8[ r8] r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/784130cc/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/784130cc/lilypond/part_II.ly deleted file mode 100644 index 3a20dd1..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/784130cc/lilypond/part_II.ly +++ /dev/null @@ -1,14 +0,0 @@ -{ - { r2. r8[ dis'8^\markup { \pad-markup #0.2 "+39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }}] ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'4 ~ dis'8[ e'8^\markup { \pad-markup #0.2 "+9"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↓" }}] ~ e'4 gis'4^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { gis'2. ~ gis'8.[ r16] } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/784130cc/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/784130cc/lilypond/part_III.ly deleted file mode 100644 index 6d5d2d3..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/784130cc/lilypond/part_III.ly +++ /dev/null @@ -1,14 +0,0 @@ -{ - { r1 } - \bar "|" - { r2 r8[ c'8^\markup { \pad-markup #0.2 "+49"}] ~ c'4 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'2 r2 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/784130cc/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/784130cc/lilypond/part_IV.ly deleted file mode 100644 index ed76315..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/784130cc/lilypond/part_IV.ly +++ /dev/null @@ -1,14 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r4 r8[ c8^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ c2 ~ } - \bar "|" - { c8[ a,8^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }}] ~ a,2. ~ } - \bar "|" - { a,2. ~ a,16[ r8.] } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/79e0a4a7_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/79e0a4a7_code.scd deleted file mode 100644 index 8e9fe42..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/79e0a4a7_code.scd +++ /dev/null @@ -1,943 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/79e0a4a7_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/79e0a4a7_mus_model.json deleted file mode 100644 index 4a70a1c..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/79e0a4a7_mus_model.json +++ /dev/null @@ -1,47 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 4.75 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 4.25 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ 2, -1, -1, -1, 1, 0 ] ], 1.75 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, 0, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ] ], 1.5 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, 0, 0, -1, 1, 0 ], [ 3, -2, 0, -1, 1, -1 ] ], 4.375 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ "Rest" ], [ 1, 0, 0, -1, 1, 0 ], [ 3, -2, 0, -1, 1, -1 ] ], 1.125 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ 3, -2, 0, -1, 1, -1 ] ], 1.5 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0.75 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 6.0 ] - ] - ] -], -"last_changes": -[ - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 1, -1 ], [ 1, 0, 0, -1, 1, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, -1, 0, -1, 1, -1 ], [ 2, -1, -1, -1, 1, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, 0, 0, -1, 1, 0 ], [ 2, -1, -1, -1, 1, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 1, 0, 0, -1, 1, 0 ], [ 3, -2, 0, -1, 1, -1 ] ] -], -"cur_uid": "79e0a4a7", -"ref_uid": "6fb60ab6", -"order_seed": 216475, -"dur_seed": 359011, -"motifs_seed": 501751, -"entrances_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.9230769230769, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.9230769230769, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.9230769230769, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -3600, -312 ], [ -1872, 1378 ], [ -145, 1583 ], [ -182, 1527 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.082304526748971, 0.99431818181818, 0.14197530864198, 0, 1, 0 ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 1, 0 ], [ 3, 2, 3 ], [ ] ] -], -"sus_weights": [ 0, 0.65, 0 ], -"order_size": [ 1, 1 ], -"passages_size": [ 1, 6 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/lilypond/part_I.ly deleted file mode 100644 index 3d68499..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/lilypond/part_I.ly +++ /dev/null @@ -1,28 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2 a'2^\markup { \pad-markup #0.2 "-6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'8[ a'8^\markup { \pad-markup #0.2 "+38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↓" }}] ~ a'2. ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'2 ~ a'8[ r8] r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/lilypond/part_II.ly deleted file mode 100644 index 771f45e..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/lilypond/part_II.ly +++ /dev/null @@ -1,28 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r4 r8[ gis'8^\markup { \pad-markup #0.2 "-18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ gis'2 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'2. ~ gis'8[ r8] } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/lilypond/part_III.ly deleted file mode 100644 index c1f7fda..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/lilypond/part_III.ly +++ /dev/null @@ -1,28 +0,0 @@ -{ - { fis'1^\markup { \pad-markup #0.2 "-21"} ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'4 ~ fis'16[ r8.] r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/lilypond/part_IV.ly deleted file mode 100644 index 5984926..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/79e0a4a7/lilypond/part_IV.ly +++ /dev/null @@ -1,28 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r4 r8[ cis'8^\markup { \pad-markup #0.2 "-19"}] ~ cis'2 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/7d3c9a80_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/7d3c9a80_code.scd deleted file mode 100644 index a98b916..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/7d3c9a80_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/7d3c9a80_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/7d3c9a80_mus_model.json deleted file mode 100644 index e6e1f1a..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/7d3c9a80_mus_model.json +++ /dev/null @@ -1,48 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 6.25 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 4.25 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ "Rest" ], [ 3, -2, 0, -1, 0, 0 ] ], 1.75 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 3, -2, 0, -1, 1, -1 ], [ 3, -2, 0, -1, 0, 0 ] ], 2.75 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 3, -2, 0, -1, 1, -1 ], [ 2, -1, 0, -1, 1, 0 ] ], 3.875 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ "Rest" ], [ 3, -2, 0, -1, 1, -1 ], [ 2, -1, 0, -1, 1, 0 ] ], 1.75 ], - [ [ [ 1, -1, 0, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ 2, -1, 0, -1, 1, 0 ] ], 0.75 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 2, -1, 0, -1, 1, 0 ] ], 1.25 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 5.375 ] - ] - ] -], -"last_changes": -[ - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 3, -2, 0, -2, 1, 0 ], [ 3, -3, 0, -1, 1, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 3, -2, 0, -2, 1, 0 ], [ 2, -2, 0, -1, 2, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 3, -2, 0, -2, 1, 0 ], [ 3, -2, 0, -1, 0, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 3, -2, 0, -1, 1, -1 ], [ 3, -2, 0, -1, 0, 0 ] ], - [ [ 1, -1, 0, -1, 1, 0 ], [ 2, -2, 0, -1, 1, 0 ], [ 3, -2, 0, -1, 1, -1 ], [ 2, -1, 0, -1, 1, 0 ] ] -], -"cur_uid": "7d3c9a80", -"ref_uid": "43b009ff", -"order_seed": 216475, -"dur_seed": 155918, -"motifs_seed": 903149, -"entrances_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 1.1904761904762, 3.3333333333333, 0.71, 1.92, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -3600, -312 ], [ -1872, 1378 ], [ -145, 1583 ], [ -182, 1527 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.082304526748971, 0.99431818181818, 0.14197530864198, 0, 1, 0 ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 1, 0 ], [ 3, 2, 3 ], [ ] ] -], -"sus_weights": [ 0, 0.65, 0 ], -"order_size": [ 1, 1 ], -"passages_size": [ 1, 6 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/lilypond/part_I.ly deleted file mode 100644 index e9da74f..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/lilypond/part_I.ly +++ /dev/null @@ -1,30 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r4 c''2.^\markup { \pad-markup #0.2 "+27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↓" }} ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''2 cis''2^\markup { \pad-markup #0.2 "-19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''4 ~ cis''16[ r8.] r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/lilypond/part_II.ly deleted file mode 100644 index 544ce2c..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/lilypond/part_II.ly +++ /dev/null @@ -1,30 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r8[ a'8^\markup { \pad-markup #0.2 "+38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↓" }}] ~ a'2. ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'4 ~ a'16[ r8.] r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/lilypond/part_III.ly deleted file mode 100644 index 924f946..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/lilypond/part_III.ly +++ /dev/null @@ -1,30 +0,0 @@ -{ - { fis'1^\markup { \pad-markup #0.2 "-21"} ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'4 ~ fis'8.[ r16] r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/lilypond/part_IV.ly deleted file mode 100644 index 91a8502..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/7d3c9a80/lilypond/part_IV.ly +++ /dev/null @@ -1,30 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r8[ cis'8^\markup { \pad-markup #0.2 "-19"}] ~ cis'2. ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'2 ~ cis'8.[ r16] r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/7edbdceb_code.scd b/resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/7edbdceb_code.scd deleted file mode 100644 index a98b916..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/7edbdceb_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/7edbdceb_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/7edbdceb_mus_model.json deleted file mode 100644 index fe59e9c..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/7edbdceb_mus_model.json +++ /dev/null @@ -1,53 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 1, 0, 1, -2, 1, 1 ] ], 1.75 ], - [ [ [ "Rest" ], [ "Rest" ], [ 1, 0, 1, -2, 0, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], 1.5 ] - ], - [ - [ [ [ "Rest" ], [ "Rest" ], [ 1, 0, 1, -2, 0, 1 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ 1, -1, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 0, 1 ], [ "Rest" ] ], 1.5 ], - [ [ [ "Rest" ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 2, -2, 2, 0 ], [ "Rest" ] ], 0 ], - [ [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 2, -2, 2, 0 ], [ "Rest" ] ], 0.75 ], - [ [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ "Rest" ] ], 0.75 ], - [ [ [ -1, -1, 1, -1, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ "Rest" ] ], 1.625 ], - [ [ [ -1, -1, 1, -1, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ "Rest" ], [ "Rest" ] ], 1.125 ], - [ [ [ -1, -1, 1, -1, 2, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0.625 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 2.375 ] - ] - ] -], -"last_changes": -[ - [ [ 1, -1, 1, -3, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 0, 1 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ 1, -1, 1, -3, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 2, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 1, -1, 2, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ 0, -1, 1, -2, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ], - [ [ -1, -1, 1, -1, 2, 0 ], [ 1, -1, 1, -2, 2, 0 ], [ 2, -2, 1, -2, 2, 0 ], [ 1, 0, 1, -2, 1, 1 ] ] -], -"cur_uid": "7edbdceb", -"ref_uid": "6d635e88", -"order_seed": 516056, -"dur_seed": 358555, -"motifs_seed": 481455, -"entrances_probs_vals": [ 0.18, 0.28, 1.4285714285714, 0.47, 1.62, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0.29, 0, 1.1111111111111, 0.65934065934066, 1.37, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0.18, 0.28, 1.4285714285714, 0.47, 1.62, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2411.1455108359, -850.77399380805 ], [ -1872, 450 ], [ -479, 1304.0247678019 ], [ -368, 1173.9938080495 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.082304526748971, 0.99431818181818, 0.33950617283951, 0, 0.72839506172839, 0, 1, 0 ], -"passages_weights": [ 0.35, 0.42, 0.75, 0.9, 0.93 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 3 ], [ 2 ], [ 0, 1 ] ], - [ [ 1 ], [ 2, 0, 2, 0 ], [ 3 ] ] -], -"sus_weights": [ 0.41, 0, 0 ], -"order_size": [ 2, 6 ], -"passages_size": [ 0, 5 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/lilypond/part_I.ly deleted file mode 100644 index 18a5337..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/lilypond/part_I.ly +++ /dev/null @@ -1,14 +0,0 @@ -{ - { ais'1^\markup { \pad-markup #0.2 "+41"} ~ } - \bar "|" - { ais'2 ~ ais'8[ r8] r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/lilypond/part_II.ly deleted file mode 100644 index d0647dd..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/lilypond/part_II.ly +++ /dev/null @@ -1,14 +0,0 @@ -{ - { r2. r8[ f'8^\markup { \pad-markup #0.2 "-11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }}] ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'4 ~ f'8[ e'8^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}] ~ e'4 f'4^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { f'2. ~ f'8.[ r16] } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/lilypond/part_III.ly deleted file mode 100644 index 6d5d2d3..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/lilypond/part_III.ly +++ /dev/null @@ -1,14 +0,0 @@ -{ - { r1 } - \bar "|" - { r2 r8[ c'8^\markup { \pad-markup #0.2 "+49"}] ~ c'4 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'2 r2 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/lilypond/part_IV.ly deleted file mode 100644 index a86ce2c..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/7edbdceb/lilypond/part_IV.ly +++ /dev/null @@ -1,14 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r4 r8[ c8^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ c2 ~ } - \bar "|" - { c8[ ais,8^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }}] ~ ais,2. ~ } - \bar "|" - { ais,2. ~ ais,16[ r8.] } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_1/tmp/tmp_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_1/tmp/tmp_mus_model.json deleted file mode 100644 index 1beabb8..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_1/tmp/tmp_mus_model.json +++ /dev/null @@ -1,78 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 2, -1, 1, -2, 1, 0 ], [ "Rest" ] ], 2.75 ], - [ [ [ 2, -1, 1, -2, 0, 0 ], [ "Rest" ], [ 2, -1, 1, -2, 1, 0 ], [ "Rest" ] ], 0.375 ], - [ [ [ 1, -1, 2, -2, 1, 0 ], [ "Rest" ], [ 2, -1, 1, -2, 1, 0 ], [ "Rest" ] ], 3.75 ] - ], - [ - [ [ [ 1, -1, 2, -2, 1, 0 ], [ "Rest" ], [ 2, -1, 1, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 0 ], - [ [ [ 1, -1, 2, -2, 1, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ 2, -1, 1, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 3.375 ], - [ [ [ 1, -1, 2, -2, 1, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ 3, -3, 1, -2, 0, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 1 ], - [ [ [ 1, -1, 2, -2, 1, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ 0, 0, 2, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 2 ] - ], - [ - [ [ [ 0, 1, 2, -2, 1, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ 0, 0, 2, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 1.125 ], - [ [ [ 2, -3, 1, -1, 1, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ 0, 0, 2, -2, 1, 0 ], [ 2, -2, 1, -1, 1, 0 ] ], 3 ] - ], - [ - [ [ [ 2, -3, 1, -1, 1, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ 0, 0, 2, -2, 1, 0 ], [ 2, -3, 0, -1, 1, 0 ] ], 0.875 ], - [ [ [ 2, -3, 1, -1, 1, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ 0, 0, 2, -2, 1, 0 ], [ 1, -3, 1, 0, 1, 0 ] ], 1.375 ] - ], - [ - [ [ [ 1, -3, 1, 0, 0, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ 0, 0, 2, -2, 1, 0 ], [ 1, -3, 1, 0, 1, 0 ] ], 1.125 ], - [ [ [ 3, -3, 1, -2, 1, -1 ], [ 3, -3, 1, -2, 1, 0 ], [ 0, 0, 2, -2, 1, 0 ], [ 1, -3, 1, 0, 1, 0 ] ], 1.875 ] - ], - [ - [ [ [ 3, -3, 1, -2, 1, -1 ], [ 3, -3, 1, -2, 1, 0 ], [ 0, 0, 2, -2, 1, 0 ], [ 1, 0, 1, -2, 1, 0 ] ], 0.875 ], - [ [ [ 3, -3, 1, -2, 1, -1 ], [ 3, -3, 1, -2, 1, 0 ], [ 0, 0, 2, -2, 1, 0 ], [ 0, 0, 2, -2, 2, 0 ] ], 2.125 ] - ], - [ - [ [ [ 3, -4, 1, -2, 1, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ 0, 0, 2, -2, 1, 0 ], [ 0, 0, 2, -2, 2, 0 ] ], 0.875 ], - [ [ [ 3, -3, 1, -2, 0, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ 0, 0, 2, -2, 1, 0 ], [ 0, 0, 2, -2, 2, 0 ] ], 1.625 ], - [ [ [ 3, -3, 1, -2, 0, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ "Rest" ], [ 0, 0, 2, -2, 2, 0 ] ], 0.75 ], - [ [ [ "Rest" ], [ 3, -3, 1, -2, 1, 0 ], [ "Rest" ], [ 0, 0, 2, -2, 2, 0 ] ], 1.125 ], - [ [ [ "Rest" ], [ 3, -3, 1, -2, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 1.25 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 4.75 ] - ] - ] -], -"last_changes": -[ - [ [ 3, -3, 1, -2, 1, -1 ], [ 3, -3, 1, -2, 1, 0 ], [ 0, 0, 2, -2, 1, 0 ], [ 1, -3, 1, 0, 1, 0 ] ], - [ [ 3, -3, 1, -2, 1, -1 ], [ 3, -3, 1, -2, 1, 0 ], [ 0, 0, 2, -2, 1, 0 ], [ 1, 0, 1, -2, 1, 0 ] ], - [ [ 3, -3, 1, -2, 1, -1 ], [ 3, -3, 1, -2, 1, 0 ], [ 0, 0, 2, -2, 1, 0 ], [ 0, 0, 2, -2, 2, 0 ] ], - [ [ 3, -4, 1, -2, 1, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ 0, 0, 2, -2, 1, 0 ], [ 0, 0, 2, -2, 2, 0 ] ], - [ [ 3, -3, 1, -2, 0, 0 ], [ 3, -3, 1, -2, 1, 0 ], [ 0, 0, 2, -2, 1, 0 ], [ 0, 0, 2, -2, 2, 0 ] ] -], -"cur_uid": "tmp", -"ref_uid": "6ed95c4c", -"order_seed": 290117, -"dur_seed": 200959, -"motifs_seed": 970117, -"entrances_probs_vals": [ 0.75, 0, 5.0793650793651, 0, 0.5, 0.26424870466321, 0.75675675675676, 0.5, 0.5, 0.58549222797927, 0.72635135135135, 1, 0.5 ], -"passages_probs_vals": [ 0.27, 0, 2.7380952380952, 0.24725274725275, 1.48, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0.27, 0, 2.7380952380952, 0.24725274725275, 1.48, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ -1482.3529411765, 542 ], [ -1129.4117647059, 1378 ], [ -256.34674922601, 1601 ], [ -238, 1712.693498452 ] ], -"step_probs_vals": [ -1200, 1200, 0, 0, 0.19135802469136, 0.27272727272727, 0.2962962962963, 0, 0.33539094650206, 0, 0.34362139917695, 0, 0.38271604938272, 0.15340909090909, 0.39711934156379, 0.56818181818182, 0.43415637860082, 0, 0.51028806584362, 0, 0.56172839506173, 0.84090909090909, 0.61316872427984, 0, 0.69135802469136, 0.28977272727273, 0.73662551440329, 0, 0.97736625514403, 0 ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 2 ], [ 0, 0 ], [ 3, 1 ] ], - [ [ 0, 3, 1 ], [ 2, 2 ], [ ] ], - [ [ 1, 3, 2 ], [ 0, 0 ], [ ] ], - [ [ 2, 0, 1 ], [ 3, 3 ], [ ] ], - [ [ 3, 1, 2 ], [ 0, 0 ], [ ] ], - [ [ 0, 2, 1 ], [ 3, 3 ], [ ] ], - [ [ 2, 3, 1 ], [ 0, 0 ], [ ] ] -], -"sus_weights": [ 0.45, 0.3, 0.38 ], -"order_size": [ 6.0510204081633, 15.142857142857 ], -"passages_size": [ 1, 1 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2.json b/resources/resources_bak_2024_01_03/string_quartet_2.json deleted file mode 100644 index 56e0507..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2.json +++ /dev/null @@ -1,16 +0,0 @@ -{ -"ledger": -[ - "5201b8af", - "525274f2", - "41e447bc", - "74307bb4", - "628706ec", - "4c059f33", - "60adbbef", - "74b8f8d9", - "62300302", - "72dc057f", - "76e45e56" -] -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2.json_bak b/resources/resources_bak_2024_01_03/string_quartet_2.json_bak deleted file mode 100644 index d5a6964..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2.json_bak +++ /dev/null @@ -1,15 +0,0 @@ -{ -"ledger": -[ - "5201b8af", - "525274f2", - "41e447bc", - "74307bb4", - "628706ec", - "4c059f33", - "60adbbef", - "74b8f8d9", - "62300302", - "72dc057f" -] -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/40119c5a/40119c5a_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/40119c5a/40119c5a_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/40119c5a/40119c5a_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/40119c5a/40119c5a_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/40119c5a/40119c5a_mus_model.json deleted file mode 100644 index 776b240..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/40119c5a/40119c5a_mus_model.json +++ /dev/null @@ -1,58 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 4.875 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 0, 1, 0, 0, 0 ] ], 4.75 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 4.125 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ] -], -"cur_uid": "40119c5a", -"ref_uid": "77b0d2dc", -"order_seed": 921767, -"dur_seed": 954688, -"motifs_seed": 995213, -"entrances_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "true", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/41e447bc_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/41e447bc_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/41e447bc_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/41e447bc_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/41e447bc_mus_model.json deleted file mode 100644 index 105ee42..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/41e447bc_mus_model.json +++ /dev/null @@ -1,64 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 2.125 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 4.75 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 0, 1, 0, 0, 0 ] ], 2.875 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 3.375 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 1.375 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 4.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ "Rest" ], [ 0, 1, -1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ] -], -"cur_uid": "41e447bc", -"ref_uid": "77b0d2dc", -"order_seed": 921767, -"dur_seed": 954688, -"motifs_seed": 995213, -"entrances_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "true", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/lilypond/part_I.ly deleted file mode 100644 index 9aaa7f4..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/lilypond/part_I.ly +++ /dev/null @@ -1,20 +0,0 @@ -{ - { r1 } - \bar "|" - { r16[ c''8.^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ c''2. ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''4 ~ c''8.[ e'16^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ e'2 ~ } - \bar "|" - { e'2. ~ e'8[ e'8^\markup { \pad-markup #0.2 "-41"}] ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'2 ~ e'16[ dis'8.^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }}] ~ dis'4 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/lilypond/part_II.ly deleted file mode 100644 index 2fe1107..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/lilypond/part_II.ly +++ /dev/null @@ -1,20 +0,0 @@ -{ - { r1 } - \bar "|" - { r16[ e'8.^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ e'2. ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'4 ~ e'8.[ e'16^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ e'2 ~ } - \bar "|" - { e'2. ~ e'8[ f'8^\markup { \pad-markup #0.2 "-2"}] ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/lilypond/part_III.ly deleted file mode 100644 index bfe5f3a..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/lilypond/part_III.ly +++ /dev/null @@ -1,20 +0,0 @@ -{ - { r1 } - \bar "|" - { r16[ fis'8.^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }}] ~ fis'2. ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'4 ~ fis'8.[ g'16^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ g'2 ~ } - \bar "|" - { g'2. ~ g'8[ gis'8^\markup { \pad-markup #0.2 "+14"}] ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'4 a'2.^\markup { \pad-markup #0.2 "-16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }} ~ } - \bar "|" - { a'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/lilypond/part_IV.ly deleted file mode 100644 index 0787499..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/41e447bc/lilypond/part_IV.ly +++ /dev/null @@ -1,20 +0,0 @@ -{ - { c'1^\markup { \pad-markup #0.2 "+0"} ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/42c3365b/42c3365b_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/42c3365b/42c3365b_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/42c3365b/42c3365b_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/42c3365b/42c3365b_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/42c3365b/42c3365b_mus_model.json deleted file mode 100644 index 710f1b3..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/42c3365b/42c3365b_mus_model.json +++ /dev/null @@ -1,123 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 1.5 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 1.25 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, 0 ] ], 0.5 ], - [ [ [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, 0 ] ], 0.875 ], - [ [ [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 1 ] ], 1.25 ], - [ [ [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 1 ] ], 0 ] - ], - [ - [ [ [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0.75 ], - [ [ [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1.375 ], - [ [ [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0.5 ], - [ [ [ 0, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1.375 ], - [ [ [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0.75 ], - [ [ [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0.125 ], - [ [ [ -1, 0, 0, 0, 1, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1 ], - [ [ [ 0, -1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1.375 ], - [ [ [ -1, 0, 1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0.5 ] - ], - [ - [ [ [ -1, 0, 1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0.75 ], - [ [ [ -1, 0, 1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ], [ 2, -1, 0, 0, 0, -1 ] ], 0.125 ], - [ [ [ -1, -1, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ], [ 2, -1, 0, 0, 0, -1 ] ], 1.375 ], - [ [ [ -1, -1, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ], [ 2, -1, 0, -1, 0, 0 ] ], 0.125 ] - ], - [ - [ [ [ -1, -1, 0, 1, 0, 0 ], [ 1, -1, 0, -1, 0, 1 ], [ "Rest" ], [ 2, -1, 0, -1, 0, 0 ] ], 0.75 ], - [ [ [ 0, -1, 0, -1, 0, 1 ], [ 1, -1, 0, -1, 0, 1 ], [ "Rest" ], [ 2, -1, 0, -1, 0, 0 ] ], 0 ], - [ [ [ 0, -1, 0, -1, 0, 1 ], [ 2, -1, -1, -1, 0, 0 ], [ "Rest" ], [ 2, -1, 0, -1, 0, 0 ] ], 0.875 ], - [ [ [ 0, 0, 0, -1, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ], [ "Rest" ], [ 2, -1, 0, -1, 0, 0 ] ], 0.125 ], - [ [ [ 0, 0, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ "Rest" ], [ 2, -1, 0, -1, 0, 0 ] ], 0.75 ], - [ [ [ 1, -1, 0, -1, -1, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ "Rest" ], [ 2, -1, 0, -1, 0, 0 ] ], 1.375 ], - [ [ [ 0, -1, 0, -1, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ "Rest" ], [ 2, -1, 0, -1, 0, 0 ] ], 0.25 ] - ], - [ - [ [ [ 0, -1, 0, -1, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ "Rest" ], [ 1, 0, 1, -1, 0, 0 ] ], 1.125 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ "Rest" ], [ 1, 0, 1, -1, 0, 0 ] ], 1.375 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, -1, 0, 1 ], [ 1, 0, 1, -1, 0, 0 ] ], 0.25 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ], [ 1, 0, 1, -1, 0, 0 ] ], 0.625 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 0.375 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 1 ] ], 0.125 ], - [ [ [ 1, 0, 0, -1, -1, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 1 ] ], 1.5 ], - [ [ [ 1, 0, 0, -1, -1, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 1 ] ], 0.875 ] - ], - [ - [ [ [ -1, 2, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 1 ] ], 0.625 ], - [ [ [ -1, 2, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 1, 0, -1, 0, 0 ] ], 0.125 ], - [ [ [ -1, 2, 0, -1, 0, 0 ], [ 0, 1, 1, -1, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 1, 0, -1, 0, 0 ] ], 0.125 ] - ], - [ - [ [ [ -1, 2, 0, -1, 0, 0 ], [ 0, 1, 1, -1, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 2, 0, -1, 0, 0 ] ], 0.375 ], - [ [ [ -1, 2, 0, -1, 0, 0 ], [ 1, 1, 0, -1, 0, -1 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 2, 0, -1, 0, 0 ] ], 0.25 ], - [ [ [ 0, 1, 0, -1, -1, 0 ], [ 1, 1, 0, -1, 0, -1 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 2, 0, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 1, 0, -1, -1, 0 ], [ 1, 1, 0, -1, 0, -1 ], [ 0, 1, 0, -1, 0, 0 ], [ 2, 1, 0, -1, -1, 0 ] ], 1 ], - [ [ [ 0, 1, 0, -1, -1, 0 ], [ 1, 1, 0, -1, 0, -1 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 1, 0, -1, 1, 0 ] ], 0.875 ], - [ [ [ -1, 1, 0, -1, 1, 0 ], [ 1, 1, 0, -1, 0, -1 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 1, 0, -1, 1, 0 ] ], 0.875 ], - [ [ [ 0, 0, 0, -1, 0, 0 ], [ 1, 1, 0, -1, 0, -1 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 1, 0, -1, 1, 0 ] ], 1.25 ], - [ [ [ 0, 1, 0, -1, 0, -1 ], [ 1, 1, 0, -1, 0, -1 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 1, 0, -1, 1, 0 ] ], 0.375 ], - [ [ [ 0, 1, 0, -1, 0, -1 ], [ 0, 1, 1, -1, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 1, 0, -1, 1, 0 ] ], 1.5 ], - [ [ [ 0, 1, 0, -2, 0, 0 ], [ 0, 1, 1, -1, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 1, 0, -1, 1, 0 ] ], 0.375 ], - [ [ [ 0, 1, 0, -2, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 1, 0, -1, 1, 0 ] ], 0.25 ], - [ [ [ 0, 1, 0, -2, 0, 0 ], [ 0, 1, 0, -1, 1, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 1, 0, -1, 1, 0 ] ], 0.875 ] - ], - [ - [ [ [ "Rest" ], [ 0, 1, 0, -1, 1, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 1, 0, -1, 1, 0 ] ], 0.625 ], - [ [ [ "Rest" ], [ 0, 1, 0, -1, 1, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 1, 0, -1, 1, -1 ] ], 0.5 ], - [ [ [ "Rest" ], [ 0, 1, 0, -1, 1, 0 ], [ -1, 2, 0, -1, 1, 0 ], [ 1, 1, 0, -1, 1, -1 ] ], 1 ], - [ [ [ "Rest" ], [ 0, 1, 0, -1, 1, 0 ], [ 0, 1, -1, -1, 1, 0 ], [ 1, 1, 0, -1, 1, -1 ] ], 1.125 ], - [ [ [ "Rest" ], [ 0, 1, 0, -1, 1, 0 ], [ -1, 1, 0, -1, 1, 1 ], [ 1, 1, 0, -1, 1, -1 ] ], 1.375 ], - [ [ [ "Rest" ], [ 0, 1, 0, -1, 1, 0 ], [ -1, 1, 0, 0, 1, 0 ], [ 1, 1, 0, -1, 1, -1 ] ], 0 ], - [ [ [ "Rest" ], [ 0, 1, 0, -1, 1, 0 ], [ -1, 1, 0, 0, 1, 0 ], [ 0, 1, 1, -1, 1, 0 ] ], 0.125 ], - [ [ [ "Rest" ], [ 0, 1, 0, -1, 1, 0 ], [ -1, 1, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 1, 0 ] ], 1.375 ], - [ [ [ "Rest" ], [ 0, 1, 0, -1, 1, 0 ], [ -1, 2, 0, -1, 1, 0 ], [ 1, 0, 0, -1, 1, 0 ] ], 0.875 ], - [ [ [ "Rest" ], [ 0, 1, 0, -1, 1, 0 ], [ 0, 1, -1, -1, 1, 0 ], [ 1, 0, 0, -1, 1, 0 ] ], 0.375 ], - [ [ [ "Rest" ], [ 0, 1, 0, -1, 1, 0 ], [ 0, 1, -1, -1, 1, 0 ], [ 0, 1, 0, -1, 2, 0 ] ], 0.625 ], - [ [ [ "Rest" ], [ 0, 1, 0, -1, 1, 0 ], [ 0, 1, -1, -1, 1, 0 ], [ "Rest" ] ], 0.5 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, -1, 1, 0 ], [ "Rest" ] ], 0.625 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 5.125 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 1, 0, -2, 0, 0 ], [ 0, 1, 0, -1, 1, 0 ], [ -1, 1, 0, 0, 1, 0 ], [ 0, 1, 1, -1, 1, 0 ] ], - [ [ 0, 1, 0, -2, 0, 0 ], [ 0, 1, 0, -1, 1, 0 ], [ -1, 1, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 1, 0 ] ], - [ [ 0, 1, 0, -2, 0, 0 ], [ 0, 1, 0, -1, 1, 0 ], [ -1, 2, 0, -1, 1, 0 ], [ 1, 0, 0, -1, 1, 0 ] ], - [ [ 0, 1, 0, -2, 0, 0 ], [ 0, 1, 0, -1, 1, 0 ], [ 0, 1, -1, -1, 1, 0 ], [ 1, 0, 0, -1, 1, 0 ] ], - [ [ 0, 1, 0, -2, 0, 0 ], [ 0, 1, 0, -1, 1, 0 ], [ 0, 1, -1, -1, 1, 0 ], [ 0, 1, 0, -1, 2, 0 ] ] -], -"cur_uid": "42c3365b", -"ref_uid": "nil", -"order_seed": 921767, -"dur_seed": 787806, -"motifs_seed": 995213, -"entrances_probs_vals": [ 0, 0, 0, 0, 1.6208791208791, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 0, 1.6208791208791, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 0, 1.6208791208791, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 1 ], [ 0, 3, 0, 3, 0 ], [ 2 ] ], - [ [ 2 ], [ 0, 1, 1, 1, 0, 0, 0 ], [ 3 ] ], - [ [ 1 ], [ 3, 0, 3 ], [ 2 ] ], - [ [ 3 ], [ 1, 0, 1, 0, 1, 0, 0 ], [ 2 ] ], - [ [ 1 ], [ 3, 0, 2, 2, 3, 3, 0, 2 ], [ ] ], - [ [ 2 ], [ 0, 3, 1 ], [ ] ], - [ [ 2 ], [ 3, 1, 0, 3, 3, 0, 0, 0, 1, 0, 1, 1 ], [ ] ], - [ [ 1 ], [ 3, 2, 2, 2, 2, 3, 3, 2, 2, 3 ], [ 0 ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/4660b5c4/4660b5c4_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/4660b5c4/4660b5c4_code.scd deleted file mode 100644 index 57e638d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/4660b5c4/4660b5c4_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/4660b5c4/4660b5c4_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/4660b5c4/4660b5c4_mus_model.json deleted file mode 100644 index fba5fcb..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/4660b5c4/4660b5c4_mus_model.json +++ /dev/null @@ -1,59 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 4.625 ], - [ [ [ 0, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 3, -2, -2, 1, 0 ] ], 0 ], - [ [ [ 0, 3, -2, -1, 1, 0 ], [ "Rest" ], [ -1, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -2, 1, 0 ] ], 0 ], - [ [ [ 0, 3, -2, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -2, 1, 0 ] ], 5.875 ] - ], - [ - [ [ [ 0, 3, -2, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 2, 0 ], [ -1, 3, -2, -2, 1, 0 ] ], 0 ], - [ [ [ 0, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 3, -2, -1, 2, 0 ], [ -1, 3, -2, -2, 1, 0 ] ], 0 ], - [ [ [ 0, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 3, -2, -1, 2, 0 ], [ -1, 3, -2, -1, 1, -1 ] ], 6.625 ] - ], - [ - [ [ [ 0, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ 0, 3, -2, -1, 0, 0 ], [ -1, 3, -2, -1, 1, -1 ] ], 0 ], - [ [ [ 0, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ 0, 3, -2, -1, 0, 0 ], [ -2, 3, -1, -1, 1, 0 ] ], 0 ], - [ [ [ 0, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ 0, 3, -2, -1, 0, 0 ], [ -2, 3, -1, -1, 1, 0 ] ], 4.875 ], - [ [ [ 0, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ "Rest" ], [ -2, 3, -1, -1, 1, 0 ] ], 0 ], - [ [ [ 0, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ -2, 3, -1, -1, 1, 0 ] ], 0 ], - [ [ [ 0, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 6.0 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 3, -2, -1, 2, 0 ], [ -1, 3, -2, -2, 1, 0 ] ], - [ [ 0, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 3, -2, -1, 2, 0 ], [ -1, 3, -2, -1, 1, -1 ] ], - [ [ 0, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ 0, 3, -2, -1, 0, 0 ], [ -1, 3, -2, -1, 1, -1 ] ], - [ [ 0, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ 0, 3, -2, -1, 0, 0 ], [ -2, 3, -1, -1, 1, 0 ] ], - [ [ 0, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ 0, 3, -2, -1, 0, 0 ], [ -2, 3, -1, -1, 1, 0 ] ] -], -"cur_uid": "4660b5c4", -"ref_uid": "4c059f33", -"order_seed": 706160, -"dur_seed": 659279, -"motifs_seed": 885545, -"entrances_probs_vals": [ 1, 0, 5.0793650793651, 0.47, 2.8021978021978, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 2.7380952380952, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 2.7380952380952, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8.0714285714286, 10.091836734694 ], -"passages_size": [ 0, 10 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/4a8a6e53_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/4a8a6e53_code.scd deleted file mode 100644 index 3eb3cbd..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/4a8a6e53_code.scd +++ /dev/null @@ -1,1058 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file; - file = File(path, "w"); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((dir +/+ ".." +/+ "resources" +/+ curUID).standardizePath); - File.copy(exPath, (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (dir +/+ ".." +/+ "resources" +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (dir +/+ ".." +/+ "resources" +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \".." +/+ ".." +/+ "resources" +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - -~transcribe.value(~seq, dir); - -( -//synthdefs -~stringModelBusArray = 4.collect({Bus.audio(s, 1)}); -~sineBusArray = 4.collect({Bus.audio(s, 1)}); -~bassBusArray = 1.collect({Bus.audio(s, 1)}); -~hdustBusArray = 1.collect({Bus.audio(s, 1)}); -~samplerBusArray = 2.collect({Bus.audio(s, 1)}); -~sBuf = Buffer.alloc(s, 10, 2); -SynthDef(\string_model, {arg freq, gate = 1, sustain, amp, dur, attack, release = 1, busIndex = 0; - var trig, exc, sig1, sig2, noHarms; - noHarms = rrand(20, 40); - exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01); - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip; - //sig1 = HPF.ar(sig1, 300); - Out.ar(Select.kr(busIndex, ~stringModelBusArray), sig1 * amp * EnvGen.kr(Env.adsr(attack, 0.3, 0.9, release, 0.9, -3), gate, doneAction: 2)); - //Out.ar([0, 1], sig1 * EnvGen.kr(Env.asr(dur, 0.3, 1), gate, doneAction: 2)); -}).add; - -SynthDef(\sine, {arg freq, gate = 1, sustain, amp, dur, busIndex = 0; - var sig; - sig = SinOsc.ar(freq); - Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.asr(0.3, 0.4, 0.3), gate, timeScale: dur, doneAction: 2)); - //Out.ar(Select.kr(busIndex, ~sineBusArray), sig * EnvGen.kr(Env.sine(dur), gate, doneAction: 2)); -}).add; - -SynthDef(\mixer, {arg freq, gate = 1, sustain, amp, dur, out; - var nameSpaces, sigs; - - sigs = [~stringModelBusArray, ~sineBusArray/*, ~bassBusArray, ~hdustBusArray, ~samplerBusArray*/].collect({arg busArray, i; - var nameSpace, sig; - nameSpace = ['string', 'sine', 'bass', 'hdust', 'sampler'][i]; - sig = busArray.collect({arg bus, c; In.ar(bus, 1) * NamedControl.kr(\ ++ nameSpace ++ '_volume_' ++ c, 1, 0.1)}); - sig = sig.collect({arg channel, c; Pan2.ar(channel, NamedControl.kr(\ ++ nameSpace ++ '_pan_' ++ c, i / (busArray.size - 1), 0.1) * 2 - 1)}); - sig = sig.collect({arg channel, c; channel * NamedControl.kr(\ ++ nameSpace ++ '_mute_' ++ c, 1, 0.1)}); - sig = Mix.ar(sig) * pow(NamedControl.kr(\ ++ nameSpace ++ '_volume_master', 1, 0.1), 2); - }); - - sigs = Mix.ar(sigs / 4); - Out.ar(0, sigs) -}).add; - -SynthDef(\bass, { - var switches, drone; - switches = {|i| Dust.kr(0.1)} ! 9; - drone = {|i| var harm = pow(2, 2 - (i / 3).trunc), amp = (1 / pow(harm, 2)); - SinOsc.ar(60 * harm + TRand.kr(-3, 3, switches[i]), 0, amp)} ! 9; - Out.ar(~bassBusArray[0], Mix.new(drone) * 0.2); -}).add; - -SynthDef(\sampler, { - Out.ar(~samplerBusArray, PlayBuf.ar(2, ~sBuf, BufRateScale.kr(~sBuf), doneAction: 2)) -}).add; - -// main routine -SynthDef(\hdust, { - arg gate = 0; - var hierarchical_dust, low_sine, high_sine, brown_noise, white_noise; - // this triggers the combinations of sources - // it is similar to the Supercollider UGen called dust but with a hierarchical structure - hierarchical_dust = ( - TIRand.kr(0, 1, Impulse.kr(100)) * - TIRand.kr(0, 1, Impulse.kr(10)) * - TIRand.kr(0, 1, Impulse.kr(1)) * - TIRand.kr(0, 1, Impulse.kr(0.1)) - ); - // adjust the multiplier at the end of each line for adjusting levels - // note with each trigger, each source has a 1 in 3 chance of sounding - low_sine = SinOsc.ar(76.midicps / 16) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.1; - high_sine = SinOsc.ar(76.midicps * 8) * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.01; - brown_noise = BrownNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.025; - white_noise = WhiteNoise.ar() * (TIRand.kr(0, 2, hierarchical_dust) < 1) * 0.02; - Out.ar(~hdustBusArray[0], - ((low_sine + high_sine + brown_noise + white_noise) ) - ); -}).add; - -) - -( -var bass, hdust, sampler, mixer; -/* -bass = Synth.tail(~group, \bass); -hdust = Synth.tail(~group, \hdust); -sampler = Synth.head(~group, \sampler); -*/ -mixer = Synth.tail(~group, \mixer); - -OSCdef(\mixer, {arg msg, time, addr, port; - mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4]) -}, \mixer); - -/* -OSCdef(\sampler, {arg msg, time, addr, port; - msg.postln; - sampler.free; - ~sBuf.free; - ~sBuf = Buffer.read(s, msg[1].asString.postln, action: {sampler = Synth.head(~group, \sampler)}); -}, \sampler); -*/ -) - -/* old something -( -SynthDef(\test, {arg freq, gate = 1, sustain, amp, dur; - var trig, exc, sig1, sig2, noHarms, freqFinal, start, end; - noHarms = 30; - freq = WhiteNoise.ar * 3 + freq; - freqFinal = Duty.ar((1/freq), 0, freq); - trig = Changed.ar(freqFinal); - start = Demand.ar(trig, 0, Dwhite(-1, -0.75)); - end = Demand.ar(trig, 0, Dwhite(0.75, 1)); - exc = Phasor.ar(trig, (end - start) * freqFinal / SampleRate.ir, start, end, 0) * 0.001 + Dust.ar(10000, 0.01); - - sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq), - Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}), - Array.fill(noHarms, {rrand(2, 3)}) ], exc) * 0.5).softclip; - sig1 = HPF.ar(sig1, 300); - Out.ar([0, 1], sig1 * EnvGen.kr(Env.adsr(0.3, 0.3, 0.9, 0.5, 0.9), gate, doneAction: 2)); -}).add; -) -*/ - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/4a8a6e53_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/4a8a6e53_mus_model.json deleted file mode 100644 index 150baf5..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/4a8a6e53_mus_model.json +++ /dev/null @@ -1,97 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 1.5 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 1.25 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 1 ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 1.25 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0.75 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ], [ "Rest" ] ], 1.5 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ "Rest" ] ], 1.25 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ "Rest" ] ], 1.375 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ "Rest" ] ], 0.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ "Rest" ] ], 0.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ "Rest" ] ], 0.75 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 0, 1 ], [ "Rest" ] ], 1.125 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ] ], 1.25 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ "Rest" ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ] ], 0.875 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, -1, 0, -1, 0 ] ], 0.875 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, -1, 0, -1, 0 ] ], 0.75 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 1, -1, 0 ], [ 1, 0, -1, 0, -1, 0 ] ], 1.5 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 1, -1, 0 ], [ 0, 0, 0, 0, -1, 1 ] ], 1.25 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 1, -1, 0 ], [ 0, 1, 0, 0, -1, 0 ] ], 0.625 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 1, 0, 0, -1, 0 ] ], 0.625 ], - [ [ [ 0, 0, 1, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 1, 0, 0, -1, 0 ] ], 0.625 ], - [ [ [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 1, 0, 0, -1, 0 ] ], 1.375 ], - [ [ [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 1, 0, -1, 0 ] ], 1.375 ], - [ [ [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 2, 0, 0, -1, -1, 0 ], [ 0, 0, 1, 0, -1, 0 ] ], 1.5 ], - [ [ [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 2, 0, 0, 0, -1, -1 ], [ 0, 0, 1, 0, -1, 0 ] ], 0.75 ], - [ [ [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 2, 0, 0, 0, -1, -1 ], [ 1, -1, 0, 0, -1, 0 ] ], 1 ] - ], - [ - [ [ [ 1, 0, 0, -1, -1, 0 ], [ "Rest" ], [ 2, 0, 0, 0, -1, -1 ], [ 1, -1, 0, 0, -1, 0 ] ], 0.75 ], - [ [ [ 0, -1, 0, 1, -1, 0 ], [ "Rest" ], [ 2, 0, 0, 0, -1, -1 ], [ 1, -1, 0, 0, -1, 0 ] ], 1 ], - [ [ [ 0, -1, 0, 1, -1, 0 ], [ "Rest" ], [ 2, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 0.875 ], - [ [ [ 0, -1, 0, 0, -1, 1 ], [ "Rest" ], [ 2, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 1.25 ], - [ [ [ 0, -1, 0, 0, -1, 1 ], [ "Rest" ], [ 1, -1, 0, 1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 1.125 ], - [ [ [ 1, -1, -1, 0, -1, 0 ], [ "Rest" ], [ 1, -1, 0, 1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 1 ], - [ [ [ 1, -1, -1, 0, -1, 0 ], [ "Rest" ], [ 1, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 0.75 ], - [ [ [ 1, -1, -1, 0, -1, 0 ], [ "Rest" ], [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 0.625 ], - [ [ [ 0, -1, 0, 0, 0, 0 ], [ "Rest" ], [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 0.75 ], - [ [ [ 1, -1, 0, 0, -2, 0 ], [ "Rest" ], [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 1.375 ], - [ [ [ 1, -1, 0, 0, -2, 0 ], [ "Rest" ], [ 2, -2, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 0.875 ], - [ [ [ 0, -1, 0, 0, -1, 1 ], [ "Rest" ], [ 2, -2, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 3.375 ], - [ [ [ 0, -1, 0, 0, -1, 1 ], [ "Rest" ], [ 2, -2, 0, 0, -1, 0 ], [ "Rest" ] ], 1.5 ], - [ [ [ 0, -1, 0, 0, -1, 1 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.375 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 2 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 1, 0, -1 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, -2 ] ], - [ [ 0, 0, 0, 1, 0, -1 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, 0, 0, -1 ], [ -1, 0, 0, 1, 0, -1 ] ], - [ [ 0, 0, 0, 1, 0, -1 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, 0, 0, -1 ], [ 0, 0, 0, 0, -1, 0 ] ], - [ [ 0, 0, 0, 1, 0, -1 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ] ], - [ [ 1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, -1, 0 ] ] -], -"cur_uid": "4a8a6e53", -"ref_uid": "nil", -"order_seed": 320463, -"dur_seed": 903977, -"motifs_seed": 895384, -"entrances_probs_vals": [ 0.75, 0, 10, 0, 0.5, 0.26424870466321, 0.75675675675676, 0.5, 0.5, 0.58549222797927, 0.72635135135135, 1, 0.5 ], -"passages_probs_vals": [ 0.75, 0, 10, 0, 0.5, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"exits_probs_vals": [ 0.75, 0, 10, 0, 0.5, 0.20725388601036, 0.68581081081081, 0.24093264248705, 0.34121621621622, 0.5, 0.5, 0.67616580310881, 0.81081081081081, 1, 0.5 ], -"ranges": [ [ -384, 2400 ], [ -507, 2400 ], [ -282, 2237 ], [ -1200, 2053 ] ], -"step_probs_vals": [ 0, 1200, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_weights": [ 0.75, 0.75, 0.75, 0.75, 0.75 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 1 ], [ 0, 3, 2, 3, 3, 2 ], [ ] ], - [ [ 2, 1 ], [ 3, 0, 3 ], [ ] ], - [ [ 1 ], [ 3, 2, 0 ], [ ] ] -], -"sus_weights": [ 0.75, 0.69, 0.75 ], -"order_size": [ 2, 6 ], -"passages_size": [ 0, 10 ], -"motif_edited": "true", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/lilypond/part_I.ly deleted file mode 100644 index ce99136..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/lilypond/part_I.ly +++ /dev/null @@ -1,56 +0,0 @@ -{ \numericTimeSignature - { r2. e'4^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }} ~ } - \bar "|" - { e'2 e'4^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ e'8.[ f'16^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ } - \bar "|" - { f'4 ~ f'8[ g'8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ g'4 ~ g'8[ ais'8^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ } - \bar "|" - { ais'4 ~ ais'8[ c''8^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ c''2 } - \bar "|" - { gis'4^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }} ~ gis'8.[ gis'16^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}] ~ gis'4 ~ gis'8[ f'8^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ } - \bar "|" - { f'2 e'4^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ e'8[ r8] } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2 r16[ dis'8.^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }}] ~ dis'4 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'8[ dis'8^\markup { \pad-markup #0.2 "-11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }}] ~ dis'2 d'4^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'4 ~ d'8[ ais8^\markup { \pad-markup #0.2 "+35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}] ~ ais2 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais8.[ b16^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }}] ~ b2. ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b2 ~ b16[ r8.] r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/lilypond/part_II.ly deleted file mode 100644 index 3c00ff8..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/lilypond/part_II.ly +++ /dev/null @@ -1,56 +0,0 @@ -{ - { c'1^\markup { \pad-markup #0.2 "+0"} ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'4 ~ c'16[ e'8.^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ e'2 ~ } - \bar "|" - { e'2 ~ e'8.[ g'16^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ g'4 ~ } - \bar "|" - { g'4 ~ g'8[ ais'8^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ ais'2 ~ } - \bar "|" - { ais'4 ~ ais'8.[ gis'16^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }}] ~ gis'2 } - \bar "|" - { gis'2^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ gis'8[ g'8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ g'4 ~ } - \bar "|" - { g'8[ f'8^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ f'2. ~ } - \bar "|" - { f'4 ~ f'8[ e'8^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }}] ~ e'2 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'16[ fis'8.^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ fis'2. ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'16[ a'8.^\markup { \pad-markup #0.2 "-20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ a'2 ~ a'16[ ais'8.^\markup { \pad-markup #0.2 "+8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↓" }}] ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'2 ~ ais'16[ b'8.^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ b'4 ~ } - \bar "|" - { b'2 ~ b'8[ a'8^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }}] ~ a'4 ~ } - \bar "|" - { a'2 ~ a'8.[ fis'16^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}] ~ fis'4 ~ } - \bar "|" - { fis'16[ f'8.^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }}] ~ f'2. ~ } - \bar "|" - { f'4 ~ f'8.[ e'16^\markup { \pad-markup #0.2 "+45"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }}] ~ e'2 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'4 ~ e'16[ r8.] r2 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/lilypond/part_III.ly deleted file mode 100644 index 75dcb1c..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/lilypond/part_III.ly +++ /dev/null @@ -1,56 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r16[ ais8.^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ ais2. ~ } - \bar "|" - { ais2. gis4^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { gis16[ fis8.^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }}] ~ fis2. ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis2 ~ fis8.[ r16] r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/lilypond/part_IV.ly deleted file mode 100644 index 41471e8..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/4a8a6e53/lilypond/part_IV.ly +++ /dev/null @@ -1,56 +0,0 @@ -{ - { r4 r8.[ c'16^\markup { \pad-markup #0.2 "+0"}] ~ c'2 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 } - \bar "|" - { b1^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b4 ~ b8[ ais8^\markup { \pad-markup #0.2 "+35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}] ~ ais8.[ a16^\markup { \pad-markup #0.2 "-20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }}] ~ a4 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a16[ a8.^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }}] ~ a2. } - \bar "|" - { gis1^\markup { \pad-markup #0.2 "-13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }} ~ } - \bar "|" - { gis8.[ gis16^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }}] ~ gis2. ~ } - \bar "|" - { gis4 ~ gis8[ f8^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ f4 fis4^\markup { \pad-markup #0.2 "-5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }} ~ } - \bar "|" - { fis2. ~ fis8[ gis8^\markup { \pad-markup #0.2 "-13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }}] ~ } - \bar "|" - { gis1 ~ } - \bar "|" - { gis1 ~ } - \bar "|" - { gis1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/4c059f33_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/4c059f33_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/4c059f33_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/4c059f33_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/4c059f33_mus_model.json deleted file mode 100644 index fd5c9df..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/4c059f33_mus_model.json +++ /dev/null @@ -1,58 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 3, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ -2, 3, -1, -1, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ], [ -2, 3, -1, -1, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ] ], 4.875 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ -1, 3, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ -1, 3, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ -2, 3, -1, -1, 1, 0 ] ], 4.75 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -3, -1, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ] ], 4.125 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -3, -1, 1, 0 ], [ "Rest" ], [ -1, 3, -2, -1, 1, -1 ] ], 0 ], - [ [ [ "Rest" ], [ -1, 3, -3, -1, 1, 0 ], [ "Rest" ], [ -1, 3, -2, -1, 1, -1 ] ], 0 ], - [ [ [ "Rest" ], [ -1, 3, -3, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 2, 0 ], [ 0, 3, -1, -1, 1, 0 ], [ -1, 4, -2, -1, 1, 0 ] ], - [ [ 0, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 2, 0 ], [ 0, 3, -1, -1, 1, 0 ], [ 0, 3, -3, -1, 1, 0 ] ], - [ [ 0, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 2, 0 ], [ 1, 3, -2, -1, 1, -1 ], [ 0, 3, -3, -1, 1, 0 ] ], - [ [ 0, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 2, 0 ], [ 1, 3, -2, -1, 1, -1 ], [ -1, 3, -2, -1, 1, 1 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ -1, 3, -2, -1, 1, 1 ] ] -], -"cur_uid": "4c059f33", -"ref_uid": "628706ec", -"order_seed": 706160, -"dur_seed": 146047, -"motifs_seed": 575591, -"entrances_probs_vals": [ 1, 0, 0, 0.47, 2.8021978021978, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0.77, 0, 0, 0, 1.6208791208791, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "true", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/lilypond/part_I.ly deleted file mode 100644 index e46bd01..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/lilypond/part_I.ly +++ /dev/null @@ -1,16 +0,0 @@ -{ - { r2 a2^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a2. ~ a8.[ cis16^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis4 ~ cis16[ cis8.^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ cis2 ~ } - \bar "|" - { cis1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/lilypond/part_II.ly deleted file mode 100644 index c17645f..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/lilypond/part_II.ly +++ /dev/null @@ -1,16 +0,0 @@ -{ - { r2 cis2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis2. ~ cis8.[ cis16^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis4 ~ cis16[ d8.^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ d2 ~ } - \bar "|" - { d1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/lilypond/part_III.ly deleted file mode 100644 index f07edd8..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/lilypond/part_III.ly +++ /dev/null @@ -1,16 +0,0 @@ -{ - { r2 e2^\markup { \pad-markup #0.2 "-36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }} ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e2. ~ e8.[ e16^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e4 ~ e16[ f8.^\markup { \pad-markup #0.2 "+29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}] ~ f2 ~ } - \bar "|" - { f1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/lilypond/part_IV.ly deleted file mode 100644 index 4db8109..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/4c059f33/lilypond/part_IV.ly +++ /dev/null @@ -1,16 +0,0 @@ -{ - { a,1^\markup { \pad-markup #0.2 "+16"} ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/5201b8af_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/5201b8af_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/5201b8af_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/5201b8af_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/5201b8af_mus_model.json deleted file mode 100644 index aa90760..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/5201b8af_mus_model.json +++ /dev/null @@ -1,58 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 4.875 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 0, 1, 0, 0, 0 ] ], 4.75 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 4.125 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ] -], -"cur_uid": "5201b8af", -"ref_uid": "77b0d2dc", -"order_seed": 921767, -"dur_seed": 954688, -"motifs_seed": 995213, -"entrances_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "true", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/lilypond/part_I.ly deleted file mode 100644 index 01ab702..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/lilypond/part_I.ly +++ /dev/null @@ -1,16 +0,0 @@ -{ - { r2 c''2^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''2. ~ c''8.[ e'16^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'4 ~ e'16[ e'8.^\markup { \pad-markup #0.2 "-41"}] ~ e'2 ~ } - \bar "|" - { e'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/lilypond/part_II.ly deleted file mode 100644 index f176e75..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/lilypond/part_II.ly +++ /dev/null @@ -1,16 +0,0 @@ -{ - { r2 e'2^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'2. ~ e'8.[ e'16^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'4 ~ e'16[ f'8.^\markup { \pad-markup #0.2 "-2"}] ~ f'2 ~ } - \bar "|" - { f'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/lilypond/part_III.ly deleted file mode 100644 index 5f83063..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/lilypond/part_III.ly +++ /dev/null @@ -1,16 +0,0 @@ -{ - { r2 fis'2^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }} ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'2. ~ fis'8.[ g'16^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'4 ~ g'16[ gis'8.^\markup { \pad-markup #0.2 "+14"}] ~ gis'2 ~ } - \bar "|" - { gis'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/lilypond/part_IV.ly deleted file mode 100644 index 67fc5d0..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/5201b8af/lilypond/part_IV.ly +++ /dev/null @@ -1,16 +0,0 @@ -{ - { c'1^\markup { \pad-markup #0.2 "+0"} ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/525274f2/525274f2_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/525274f2/525274f2_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/525274f2/525274f2_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/525274f2/525274f2_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/525274f2/525274f2_mus_model.json deleted file mode 100644 index a8be70b..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/525274f2/525274f2_mus_model.json +++ /dev/null @@ -1,66 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 3.375 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 0, 1, 0, 0, 0 ] ], 1.25 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 3.125 ] - ], - [ - [ [ [ 1, 0, -1, 0, 0, -1 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ 1, 0, -1, 0, 0, -1 ], [ 1, 0, 1, 0, 0, -1 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 2.25 ] - ], - [ - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 1, 0, 1, 0, 0, -1 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 2.625 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ] ], 0 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ 2, -1, 0, -1, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ] -], -"cur_uid": "525274f2", -"ref_uid": "77b0d2dc", -"order_seed": 921767, -"dur_seed": 954688, -"motifs_seed": 995213, -"entrances_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "true", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/525274f2/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_2/525274f2/lilypond/part_I.ly deleted file mode 100644 index a568867..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/525274f2/lilypond/part_I.ly +++ /dev/null @@ -1,14 +0,0 @@ -{ - { r2 c''2^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''8.[ e'16^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ e'2 ~ e'16[ e'8.^\markup { \pad-markup #0.2 "-41"}] ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/525274f2/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_2/525274f2/lilypond/part_II.ly deleted file mode 100644 index 9a7f7ed..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/525274f2/lilypond/part_II.ly +++ /dev/null @@ -1,14 +0,0 @@ -{ - { r2 e'2^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'8.[ e'16^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ e'2 ~ e'16[ f'8.^\markup { \pad-markup #0.2 "-2"}] ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/525274f2/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_2/525274f2/lilypond/part_III.ly deleted file mode 100644 index ac151b0..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/525274f2/lilypond/part_III.ly +++ /dev/null @@ -1,14 +0,0 @@ -{ - { r2 fis'2^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }} ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'8.[ g'16^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ g'2 ~ g'16[ gis'8.^\markup { \pad-markup #0.2 "+14"}] ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'4 ~ gis'8[ g'8^\markup { \pad-markup #0.2 "+46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }}] ~ g'2 ~ } - \bar "|" - { g'2 g'2^\markup { \pad-markup #0.2 "+29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/525274f2/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_2/525274f2/lilypond/part_IV.ly deleted file mode 100644 index e646018..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/525274f2/lilypond/part_IV.ly +++ /dev/null @@ -1,14 +0,0 @@ -{ - { c'1^\markup { \pad-markup #0.2 "+0"} ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'4 ~ c'8[ c'8^\markup { \pad-markup #0.2 "-27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↓" }}] ~ c'2 ~ } - \bar "|" - { c'2 b2^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↓" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/60adbbef_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/60adbbef_code.scd deleted file mode 100644 index 57e638d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/60adbbef_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/60adbbef_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/60adbbef_mus_model.json deleted file mode 100644 index 748c135..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/60adbbef_mus_model.json +++ /dev/null @@ -1,65 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3.75 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ -2, 3, -1, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 4.75 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 2, -2, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 2, -2, -1, 1, 0 ], [ -1, 3, -3, -1, 1, 0 ] ], 7.125 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -2, 3, -2, -1, 2, 0 ], [ -1, 3, -3, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -2, 3, -2, -1, 2, 0 ], [ 0, 3, -2, -1, 1, -1 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ -2, 3, -2, -1, 2, 0 ], [ 0, 3, -2, -1, 1, -1 ] ], 4.5 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ], [ 0, 3, -2, -1, 1, -1 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ], [ -1, 3, -1, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ], [ -1, 3, -1, -1, 1, 0 ] ], 6.875 ], - [ [ [ "Rest" ], [ -1, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ], [ -1, 3, -1, -1, 1, 0 ] ], 0 ], - [ [ [ "Rest" ], [ -1, 3, -2, -1, 1, 0 ], [ "Rest" ], [ -1, 3, -1, -1, 1, 0 ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ -1, 3, -1, -1, 1, 0 ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 10.75 ] - ] - ] -], -"last_changes": -[ - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -2, 3, -2, -1, 2, 0 ], [ 0, 3, -2, -1, 1, -1 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ -2, 3, -2, -1, 2, 0 ], [ 0, 3, -2, -1, 1, -1 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ], [ 0, 3, -2, -1, 1, -1 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ], [ -1, 3, -1, -1, 1, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ], [ -1, 3, -1, -1, 1, 0 ] ] -], -"cur_uid": "60adbbef", -"ref_uid": "4c059f33", -"order_seed": 824152, -"dur_seed": 266394, -"motifs_seed": 206072, -"entrances_probs_vals": [ 1, 0, 5.0793650793651, 0.47, 2.8021978021978, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 2.7380952380952, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 2.7380952380952, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8.0714285714286, 10.091836734694 ], -"passages_size": [ 0, 10 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/lilypond/part_I.ly deleted file mode 100644 index 708ce11..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/lilypond/part_I.ly +++ /dev/null @@ -1,38 +0,0 @@ -{ - { r1 } - \bar "|" - { r2. r8[ e8^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e4 f2.^\markup { \pad-markup #0.2 "+29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { f1 ~ } - \bar "|" - { f1 ~ } - \bar "|" - { f2. ~ f16[ cis'8.^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'16[ cis'8.^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ cis'2. ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'2 r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/lilypond/part_II.ly deleted file mode 100644 index 7fea40e..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/lilypond/part_II.ly +++ /dev/null @@ -1,38 +0,0 @@ -{ - { r1 } - \bar "|" - { r2. r8[ cis8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis4 d2.^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d2. ~ d16[ dis8.^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }}] ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis16[ e8.^\markup { \pad-markup #0.2 "-36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }}] ~ e2. ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e2 r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/lilypond/part_III.ly deleted file mode 100644 index dde5fb8..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/lilypond/part_III.ly +++ /dev/null @@ -1,38 +0,0 @@ -{ - { r1 } - \bar "|" - { r2. r8[ a8^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a4 fis2.^\markup { \pad-markup #0.2 "-44"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }} ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis2. ~ fis16[ g8.^\markup { \pad-markup #0.2 "-15"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g16[ a8.^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ a2. ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a2 r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/lilypond/part_IV.ly deleted file mode 100644 index 98319b9..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/60adbbef/lilypond/part_IV.ly +++ /dev/null @@ -1,38 +0,0 @@ -{ - { a,1^\markup { \pad-markup #0.2 "+16"} ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,2 r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/61e92979/61e92979_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/61e92979/61e92979_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/61e92979/61e92979_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/61e92979/61e92979_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/61e92979/61e92979_mus_model.json deleted file mode 100644 index 413129a..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/61e92979/61e92979_mus_model.json +++ /dev/null @@ -1,67 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 3.375 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 0, 1, 0, 0, 0 ] ], 1.25 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 3.125 ] - ], - [ - [ [ [ 1, 0, -1, 0, 0, -1 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ 1, 0, -1, 0, 0, -1 ], [ 1, 0, 1, 0, 0, -1 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 2.25 ] - ], - [ - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 1, 0, 1, 0, 0, -1 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 2.625 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ] ], 0 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ 2, -1, 0, -1, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 10 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 0, 1, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ] -], -"cur_uid": "61e92979", -"ref_uid": "nil", -"order_seed": 921767, -"dur_seed": 954688, -"motifs_seed": 995213, -"entrances_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "true", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/62300302/62300302_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/62300302/62300302_code.scd deleted file mode 100644 index 57e638d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/62300302/62300302_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/62300302/62300302_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/62300302/62300302_mus_model.json deleted file mode 100644 index dfaef7d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/62300302/62300302_mus_model.json +++ /dev/null @@ -1,77 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 2.25 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ -2, 3, -2, 0, 1, 0 ] ], 1.5 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ 0, 2, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ] ], 1.875 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 2, 0 ], [ 0, 2, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ] ], 2.625 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 2, 0 ], [ -1, 3, -2, -1, 2, 0 ], [ -2, 3, -2, 0, 1, 0 ] ], 1.25 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ], [ -1, 3, -2, -1, 2, 0 ], [ -2, 3, -2, 0, 1, 0 ] ], 1.5 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ], [ -1, 3, -2, -1, 2, 0 ], [ -1, 3, -2, -2, 1, 0 ] ], 2.25 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ], [ 0, 3, -2, -1, 0, 0 ], [ -1, 3, -2, -2, 1, 0 ] ], 1.5 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ], [ 0, 3, -2, -1, 0, 0 ], [ -1, 3, -2, -1, 1, -1 ] ], 2 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ], [ 0, 3, -2, -1, 0, 0 ], [ -1, 3, -2, -1, 1, -1 ] ], 1.75 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ], [ 0, 3, -2, -2, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ] ], 1.375 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ], [ 0, 3, -2, -2, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ] ], 2.125 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ 0, 3, -2, -2, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ] ], 1.125 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ 0, 3, -2, -1, 1, -1 ], [ -1, 2, -2, -1, 1, 0 ] ], 2.125 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ 0, 3, -2, -1, 1, -1 ], [ -1, 2, -2, -1, 1, 0 ] ], 1.75 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ 0, 3, -2, -1, 1, -1 ], [ -2, 3, -2, -1, 2, 0 ] ], 2 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ 0, 3, -2, -1, 1, -1 ], [ -1, 3, -2, -1, 0, 0 ] ], 1 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ 0, 2, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ] ], 1 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ], [ 0, 2, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ] ], 1.5 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ], [ "Rest" ], [ -1, 3, -2, -1, 0, 0 ] ], 1 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 1.375 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0 ] - ] - ] -], -"last_changes": -[ - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ 0, 3, -2, -1, 1, -1 ], [ -1, 2, -2, -1, 1, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ 0, 3, -2, -1, 1, -1 ], [ -2, 3, -2, -1, 2, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ 0, 3, -2, -1, 1, -1 ], [ -1, 3, -2, -1, 0, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ 0, 2, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ], [ 0, 2, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ] ] -], -"cur_uid": "62300302", -"ref_uid": "74b8f8d9", -"order_seed": 799630, -"dur_seed": 442647, -"motifs_seed": 452591, -"entrances_probs_vals": [ 1, 0, 2.9365079365079, 0.47, 2.8021978021978, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 2.7380952380952, 0.96, 2.4725274725275, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 2.7380952380952, 0.96, 2.4725274725275, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8.0714285714286, 10.091836734694 ], -"passages_size": [ 0, 10 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/62300302/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_2/62300302/lilypond/part_I.ly deleted file mode 100644 index f4f96ba..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/62300302/lilypond/part_I.ly +++ /dev/null @@ -1,36 +0,0 @@ -{ - { r1 } - \bar "|" - { r8[ g8^\markup { \pad-markup #0.2 "-15"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ g2. ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g2 b,2^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }} ~ } - \bar "|" - { b,1 ~ } - \bar "|" - { b,4 ~ b,8[ cis8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ cis2 ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis2. ~ cis8.[ d16^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d2 dis2^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }} ~ } - \bar "|" - { dis2 e2^\markup { \pad-markup #0.2 "-36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }} ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e2. r4} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/62300302/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_2/62300302/lilypond/part_II.ly deleted file mode 100644 index 158f676..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/62300302/lilypond/part_II.ly +++ /dev/null @@ -1,36 +0,0 @@ -{ - { r1 } - \bar "|" - { r2. r8[ d'8^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'8[ dis'8^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ dis'2. ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'2 ~ dis'8[ e'8^\markup { \pad-markup #0.2 "-36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ e'4 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'4 b2.^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }} ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b2 ~ b16[ cis'8.^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ cis'4 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 } - \bar "|" - { d'1^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { d'4 r2. } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/62300302/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_2/62300302/lilypond/part_III.ly deleted file mode 100644 index cebac3f..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/62300302/lilypond/part_III.ly +++ /dev/null @@ -1,36 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2. r16[ dis8.^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }}] ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis2. e4^\markup { \pad-markup #0.2 "-36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }} ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e4 ~ e8[ e8^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ e2 ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 } - \bar "|" - { fis1^\markup { \pad-markup #0.2 "-44"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }} ~ } - \bar "|" - { fis2 ~ fis8[ g8^\markup { \pad-markup #0.2 "-15"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ g4 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g2 a2^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { a1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/62300302/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_2/62300302/lilypond/part_IV.ly deleted file mode 100644 index 19d2217..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/62300302/lilypond/part_IV.ly +++ /dev/null @@ -1,36 +0,0 @@ -{ - { a,1^\markup { \pad-markup #0.2 "+16"} ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/628706ec/628706ec_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/628706ec/628706ec_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/628706ec/628706ec_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/628706ec/628706ec_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/628706ec/628706ec_mus_model.json deleted file mode 100644 index 7226160..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/628706ec/628706ec_mus_model.json +++ /dev/null @@ -1,117 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ 0, 2, -1, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 1.5 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 1.25 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 2, -1, 0, 0, 0 ] ], 0.5 ], - [ [ [ 1, 2, -1, -1, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 2, -1, 0, 0, 0 ] ], 0.875 ], - [ [ [ 1, 2, -1, -1, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ "Rest" ], [ 0, 2, -1, 0, 0, 1 ] ], 1.25 ], - [ [ [ -1, 3, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ "Rest" ], [ 0, 2, -1, 0, 0, 1 ] ], 0 ] - ], - [ - [ [ [ -1, 3, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0.75 ], - [ [ [ -1, 3, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ "Rest" ] ], 1.375 ], - [ [ [ 0, 2, -1, 0, -1, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ "Rest" ] ], 0.5 ], - [ [ [ 0, 2, -1, 0, -1, 0 ], [ 1, 2, -1, 0, -1, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ "Rest" ] ], 1.375 ], - [ [ [ 0, 2, -1, 0, -1, 0 ], [ 0, 2, -1, 0, 1, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ "Rest" ] ], 0.75 ], - [ [ [ 0, 2, -1, 0, -1, 0 ], [ 1, 1, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ "Rest" ] ], 0.125 ], - [ [ [ -1, 2, -1, 0, 1, 0 ], [ 1, 1, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ "Rest" ] ], 1 ], - [ [ [ 0, 1, -1, 0, 0, 0 ], [ 1, 1, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ "Rest" ] ], 1.375 ], - [ [ [ -1, 2, 0, 0, 0, 0 ], [ 1, 1, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ "Rest" ] ], 0.5 ] - ], - [ - [ [ [ -1, 2, 0, 0, 0, 0 ], [ 1, 1, -1, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0.75 ], - [ [ [ -1, 2, 0, 0, 0, 0 ], [ 1, 1, -1, 0, 0, 0 ], [ "Rest" ], [ 2, 1, -1, 0, 0, -1 ] ], 0.125 ], - [ [ [ -1, 1, -1, 1, 0, 0 ], [ 1, 1, -1, 0, 0, 0 ], [ "Rest" ], [ 2, 1, -1, 0, 0, -1 ] ], 1.375 ], - [ [ [ -1, 1, -1, 1, 0, 0 ], [ 1, 1, -1, 0, 0, 0 ], [ "Rest" ], [ 2, 1, -1, -1, 0, 0 ] ], 0.125 ] - ], - [ - [ [ [ -1, 1, -1, 1, 0, 0 ], [ 1, 1, -1, -1, 0, 1 ], [ "Rest" ], [ 2, 1, -1, -1, 0, 0 ] ], 0.75 ], - [ [ [ 0, 1, -1, -1, 0, 1 ], [ 1, 1, -1, -1, 0, 1 ], [ "Rest" ], [ 2, 1, -1, -1, 0, 0 ] ], 0 ], - [ [ [ 0, 1, -1, -1, 0, 1 ], [ 2, 1, -2, -1, 0, 0 ], [ "Rest" ], [ 2, 1, -1, -1, 0, 0 ] ], 0.875 ], - [ [ [ 0, 2, -1, -1, 0, 0 ], [ 2, 1, -2, -1, 0, 0 ], [ "Rest" ], [ 2, 1, -1, -1, 0, 0 ] ], 0.125 ], - [ [ [ 0, 2, -1, -1, 0, 0 ], [ 1, 2, -1, -1, 0, 0 ], [ "Rest" ], [ 2, 1, -1, -1, 0, 0 ] ], 0.75 ], - [ [ [ 1, 1, -1, -1, -1, 0 ], [ 1, 2, -1, -1, 0, 0 ], [ "Rest" ], [ 2, 1, -1, -1, 0, 0 ] ], 1.375 ], - [ [ [ 0, 1, -1, -1, 1, 0 ], [ 1, 2, -1, -1, 0, 0 ], [ "Rest" ], [ 2, 1, -1, -1, 0, 0 ] ], 0.25 ] - ], - [ - [ [ [ 0, 1, -1, -1, 1, 0 ], [ 1, 2, -1, -1, 0, 0 ], [ "Rest" ], [ 1, 2, 0, -1, 0, 0 ] ], 1.125 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 1, 2, -1, -1, 0, 0 ], [ "Rest" ], [ 1, 2, 0, -1, 0, 0 ] ], 1.375 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 1, 2, -1, -1, 0, 0 ], [ 0, 2, -1, -1, 0, 1 ], [ 1, 2, 0, -1, 0, 0 ] ], 0.25 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 1, 2, -1, -1, 0, 0 ], [ 1, 2, -2, -1, 0, 0 ], [ 1, 2, 0, -1, 0, 0 ] ], 0.625 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 1, 2, -1, -1, 0, 0 ], [ 1, 2, -2, -1, 0, 0 ], [ 1, 2, -1, 0, 0, 0 ] ], 0.375 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 1, 2, -1, -1, 0, 0 ], [ 1, 2, -2, -1, 0, 0 ], [ 1, 2, -1, -1, 0, 1 ] ], 0.125 ], - [ [ [ 1, 2, -1, -1, -1, 0 ], [ 1, 2, -1, -1, 0, 0 ], [ 1, 2, -2, -1, 0, 0 ], [ 1, 2, -1, -1, 0, 1 ] ], 1.5 ], - [ [ [ 1, 2, -1, -1, -1, 0 ], [ 1, 2, -1, -1, 0, 0 ], [ 0, 3, -1, -1, 0, 0 ], [ 1, 2, -1, -1, 0, 1 ] ], 0.875 ] - ], - [ - [ [ [ -1, 4, -1, -1, 0, 0 ], [ 1, 2, -1, -1, 0, 0 ], [ 0, 3, -1, -1, 0, 0 ], [ 1, 2, -1, -1, 0, 1 ] ], 0.625 ], - [ [ [ -1, 4, -1, -1, 0, 0 ], [ 1, 2, -1, -1, 0, 0 ], [ 0, 3, -1, -1, 0, 0 ], [ 1, 3, -1, -1, 0, 0 ] ], 0.125 ], - [ [ [ -1, 4, -1, -1, 0, 0 ], [ 0, 3, 0, -1, 0, 0 ], [ 0, 3, -1, -1, 0, 0 ], [ 1, 3, -1, -1, 0, 0 ] ], 0.125 ] - ], - [ - [ [ [ -1, 4, -1, -1, 0, 0 ], [ 0, 3, 0, -1, 0, 0 ], [ 0, 3, -1, -1, 0, 0 ], [ 1, 4, -1, -1, 0, 0 ] ], 0.375 ], - [ [ [ -1, 4, -1, -1, 0, 0 ], [ 1, 3, -1, -1, 0, -1 ], [ 0, 3, -1, -1, 0, 0 ], [ 1, 4, -1, -1, 0, 0 ] ], 0.25 ], - [ [ [ 0, 3, -1, -1, -1, 0 ], [ 1, 3, -1, -1, 0, -1 ], [ 0, 3, -1, -1, 0, 0 ], [ 1, 4, -1, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 3, -1, -1, -1, 0 ], [ 1, 3, -1, -1, 0, -1 ], [ 0, 3, -1, -1, 0, 0 ], [ 2, 3, -1, -1, -1, 0 ] ], 1 ], - [ [ [ 0, 3, -1, -1, -1, 0 ], [ 1, 3, -1, -1, 0, -1 ], [ 0, 3, -1, -1, 0, 0 ], [ 1, 3, -1, -1, 1, 0 ] ], 0.875 ], - [ [ [ -1, 3, -1, -1, 1, 0 ], [ 1, 3, -1, -1, 0, -1 ], [ 0, 3, -1, -1, 0, 0 ], [ 1, 3, -1, -1, 1, 0 ] ], 0.875 ], - [ [ [ 0, 2, -1, -1, 0, 0 ], [ 1, 3, -1, -1, 0, -1 ], [ 0, 3, -1, -1, 0, 0 ], [ 1, 3, -1, -1, 1, 0 ] ], 1.25 ], - [ [ [ 0, 3, -1, -1, 0, -1 ], [ 1, 3, -1, -1, 0, -1 ], [ 0, 3, -1, -1, 0, 0 ], [ 1, 3, -1, -1, 1, 0 ] ], 0.375 ], - [ [ [ 0, 3, -1, -1, 0, -1 ], [ 0, 3, 0, -1, 0, 0 ], [ 0, 3, -1, -1, 0, 0 ], [ 1, 3, -1, -1, 1, 0 ] ], 1.5 ], - [ [ [ 0, 3, -1, -2, 0, 0 ], [ 0, 3, 0, -1, 0, 0 ], [ 0, 3, -1, -1, 0, 0 ], [ 1, 3, -1, -1, 1, 0 ] ], 0.375 ], - [ [ [ 0, 3, -1, -2, 0, 0 ], [ 1, 2, -1, -1, 0, 0 ], [ 0, 3, -1, -1, 0, 0 ], [ 1, 3, -1, -1, 1, 0 ] ], 0.25 ], - [ [ [ 0, 3, -1, -2, 0, 0 ], [ 0, 3, -1, -1, 1, 0 ], [ 0, 3, -1, -1, 0, 0 ], [ 1, 3, -1, -1, 1, 0 ] ], 0.875 ] - ], - [ - [ [ [ "Rest" ], [ 0, 3, -1, -1, 1, 0 ], [ 0, 3, -1, -1, 0, 0 ], [ 1, 3, -1, -1, 1, 0 ] ], 0.625 ], - [ [ [ "Rest" ], [ 0, 3, -1, -1, 1, 0 ], [ 0, 3, -1, -1, 0, 0 ], [ 1, 3, -1, -1, 1, -1 ] ], 0.5 ], - [ [ [ "Rest" ], [ 0, 3, -1, -1, 1, 0 ], [ -1, 4, -1, -1, 1, 0 ], [ 1, 3, -1, -1, 1, -1 ] ], 1 ], - [ [ [ "Rest" ], [ 0, 3, -1, -1, 1, 0 ], [ 0, 3, -2, -1, 1, 0 ], [ 1, 3, -1, -1, 1, -1 ] ], 1.125 ], - [ [ [ "Rest" ], [ 0, 3, -1, -1, 1, 0 ], [ -1, 3, -1, -1, 1, 1 ], [ 1, 3, -1, -1, 1, -1 ] ], 1.375 ], - [ [ [ "Rest" ], [ 0, 3, -1, -1, 1, 0 ], [ -1, 3, -1, 0, 1, 0 ], [ 1, 3, -1, -1, 1, -1 ] ], 0 ], - [ [ [ "Rest" ], [ 0, 3, -1, -1, 1, 0 ], [ -1, 3, -1, 0, 1, 0 ], [ 0, 3, 0, -1, 1, 0 ] ], 0.125 ], - [ [ [ "Rest" ], [ 0, 3, -1, -1, 1, 0 ], [ -1, 3, -1, 0, 1, 0 ], [ 1, 2, -1, -1, 1, 0 ] ], 1.375 ], - [ [ [ "Rest" ], [ 0, 3, -1, -1, 1, 0 ], [ -1, 4, -1, -1, 1, 0 ], [ 1, 2, -1, -1, 1, 0 ] ], 0.875 ], - [ [ [ "Rest" ], [ 0, 3, -1, -1, 1, 0 ], [ 0, 3, -2, -1, 1, 0 ], [ 1, 2, -1, -1, 1, 0 ] ], 0.375 ], - [ [ [ "Rest" ], [ 0, 3, -1, -1, 1, 0 ], [ 0, 3, -2, -1, 1, 0 ], [ 0, 3, -1, -1, 2, 0 ] ], 0.625 ], - [ [ [ "Rest" ], [ 0, 3, -1, -1, 1, 0 ], [ 0, 3, -2, -1, 1, 0 ], [ "Rest" ] ], 0.5 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 3, -2, -1, 1, 0 ], [ "Rest" ] ], 0.625 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], - [ [ 0, 3, -2, -1, 1, 0 ], [ 0, 3, -2, -1, 1, 0 ], [ 0, 3, -2, -1, 1, 0 ], [ 0, 3, -2, -1, 1, 0 ] ] -], -"cur_uid": "628706ec", -"ref_uid": "77b0d2dc", -"order_seed": 921767, -"dur_seed": 954688, -"motifs_seed": 995213, -"entrances_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "true", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/628706ec/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_2/628706ec/lilypond/part_I.ly deleted file mode 100644 index 5057e30..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/628706ec/lilypond/part_I.ly +++ /dev/null @@ -1,46 +0,0 @@ -{ - { r1 } - \bar "|" - { r4 r8[ ais''8^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ ais''2 ~ } - \bar "|" - { ais''16[ g''8.^\markup { \pad-markup #0.2 "-42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }}] ~ g''4 ~ g''8.[ r16] r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2. r8.[ g''16^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↓" }}] ~ } - \bar "|" - { g''2 ~ g''8.[ f''16^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }}] ~ f''4 ~ } - \bar "|" - { f''1 ~ } - \bar "|" - { f''2. ~ f''16[ e''8.^\markup { \pad-markup #0.2 "+35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}] ~ } - \bar "|" - { e''1 ~ } - \bar "|" - { e''2 ais''8.^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}[ a''16^\markup { \pad-markup #0.2 "-11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }}] ~ a''4 ~ } - \bar "|" - { a''1 ~ } - \bar "|" - { a''4 gis''8^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}[ dis'''8^\markup { \pad-markup #0.2 "-47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ dis'''2 ~ } - \bar "|" - { dis'''8.[ d'''16^\markup { \pad-markup #0.2 "-1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ d'''4 ~ d'''8.[ cis'''16^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↑" }}] ~ cis'''4 ~ } - \bar "|" - { cis'''1 ~ } - \bar "|" - { cis'''1 ~ } - \bar "|" - { cis'''1 ~ } - \bar "|" - { cis'''8.[ f''16^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↓" }}] ~ f''2. ~ } - \bar "|" - { f''1 ~ } - \bar "|" - { f''8.[ f''16^\markup { \pad-markup #0.2 "-12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}] fis''2.^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } - \bar "|" - { fis''2 ~ fis''16[ g''8.^\markup { \pad-markup #0.2 "-47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↑" }}] ~ g''8[ r8]} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/628706ec/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_2/628706ec/lilypond/part_II.ly deleted file mode 100644 index 488d911..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/628706ec/lilypond/part_II.ly +++ /dev/null @@ -1,46 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r16[ ais'8.^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ ais'2. ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'2 ~ ais'16[ r8.] r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r16[ a'8^\markup { \pad-markup #0.2 "-11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }} a'16^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }}] ~ a'2. ~ } - \bar "|" - { a'2 gis'2^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'4 ~ gis'8.[ gis'16^\markup { \pad-markup #0.2 "+4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }}] ~ gis'4 ~ gis'8.[ a'16^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }}] ~ } - \bar "|" - { a'2 a'2^\markup { \pad-markup #0.2 "+43"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }} ~ } - \bar "|" - { a'8.[ b'16^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }}] ~ b'2 ~ b'8.[ gis'16^\markup { \pad-markup #0.2 "+4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }}] ~ } - \bar "|" - { gis'4 ~ gis'8[ a'8^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }}] ~ a'2} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/628706ec/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_2/628706ec/lilypond/part_III.ly deleted file mode 100644 index e86a63f..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/628706ec/lilypond/part_III.ly +++ /dev/null @@ -1,46 +0,0 @@ -{ - { ais'1^\markup { \pad-markup #0.2 "+18"} ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 } - \bar "|" - { f''2^\markup { \pad-markup #0.2 "-34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ f''8.[ e''16^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↑" }}] ~ e''4 ~ } - \bar "|" - { e''16[ dis''8.^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }}] ~ dis''2. ~ } - \bar "|" - { dis''1 ~ } - \bar "|" - { dis''2. d''4^\markup { \pad-markup #0.2 "-13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }} ~ } - \bar "|" - { d''8[ d''8^\markup { \pad-markup #0.2 "-39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }}] ~ d''4 ~ d''8[ c''8^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ c''4 ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''4 ~ c''16[ b'8.^\markup { \pad-markup #0.2 "+37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }}] ~ b'16[ b'8.^\markup { \pad-markup #0.2 "+10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↓" }}] ~ b'4 ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'4 ~ b'8[ b'8^\markup { \pad-markup #0.2 "+37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }}] ~ b'2 ~ } - \bar "|" - { b'4 ~ b'16[ c''8^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }} cis''16^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ cis''2 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/628706ec/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_2/628706ec/lilypond/part_IV.ly deleted file mode 100644 index ce23b81..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/628706ec/lilypond/part_IV.ly +++ /dev/null @@ -1,46 +0,0 @@ -{ - { r2. ais4^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { ais2 ~ ais8[ c''8^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }}] ~ c''4 ~ } - \bar "|" - { c''2 ~ c''8.[ f'16^\markup { \pad-markup #0.2 "+20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }}] ~ f'4 ~ } - \bar "|" - { f'2. f'4^\markup { \pad-markup #0.2 "-34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↓" }} ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'8[ e'8^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↑" }}] ~ e'4 ~ e'8[ dis'8^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ dis'4 ~ } - \bar "|" - { dis'4 ~ dis'16[ d'8.^\markup { \pad-markup #0.2 "+4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }}] ~ d'2 } - \bar "|" - { cis'1^\markup { \pad-markup #0.2 "-16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }} ~ } - \bar "|" - { cis'8[ d'8^\markup { \pad-markup #0.2 "-13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ d'4 ~ d'16[ c'8.^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}] ~ c'4 } - \bar "|" - { c'2^\markup { \pad-markup #0.2 "-5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }} ~ c'8.[ b16^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }}] ~ b4 ~ } - \bar "|" - { b4 ~ b8[ ais8^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }}] ~ ais2 ~ } - \bar "|" - { ais2. g'4^\markup { \pad-markup #0.2 "-3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↓" }} ~ } - \bar "|" - { g'2. ~ g'8.[ dis'16^\markup { \pad-markup #0.2 "-47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }}] ~ } - \bar "|" - { dis'2 ~ dis'8.[ d'16^\markup { \pad-markup #0.2 "-1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↓" }}] ~ d'4 ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'8[ cis'8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ cis'4 ~ cis'16[ c'8.^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }}] ~ c'4 ~ } - \bar "|" - { c'8.[ b16^\markup { \pad-markup #0.2 "+10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ b2. ~ } - \bar "|" - { b8[ ais8^\markup { \pad-markup #0.2 "-18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }}] ~ ais2 ~ ais8[ r8] } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/63bf7942/63bf7942_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/63bf7942/63bf7942_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/63bf7942/63bf7942_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/63bf7942/63bf7942_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/63bf7942/63bf7942_mus_model.json deleted file mode 100644 index 792f760..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/63bf7942/63bf7942_mus_model.json +++ /dev/null @@ -1,67 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 2.125 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 4.75 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 0, 1, 0, 0, 0 ] ], 2.875 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 3.375 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 1.375 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 4.625 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ "Rest" ], [ 0, 1, -1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 9.125 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ] -], -"cur_uid": "63bf7942", -"ref_uid": "nil", -"order_seed": 921767, -"dur_seed": 345812, -"motifs_seed": 995213, -"entrances_probs_vals": [ 1, 0, 0, 0.88, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 0, 0.88, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 0, 0.88, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/6a7a8dd9/6a7a8dd9_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/6a7a8dd9/6a7a8dd9_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/6a7a8dd9/6a7a8dd9_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/6a7a8dd9/6a7a8dd9_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/6a7a8dd9/6a7a8dd9_mus_model.json deleted file mode 100644 index bc3aae4..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/6a7a8dd9/6a7a8dd9_mus_model.json +++ /dev/null @@ -1,126 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 0, 0, 0 ] ], 3.875 ], - [ [ [ "Rest" ], [ "Rest" ], [ 1, 1, -1, -1, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 0 ], - [ [ [ -1, 1, -1, 0, 0, 1 ], [ "Rest" ], [ 1, 1, -1, -1, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 0 ], - [ [ [ -1, 1, -1, 0, 0, 1 ], [ 1, 1, -1, 0, -1, 0 ], [ 1, 1, -1, -1, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 4.25 ], - [ [ [ -1, 1, -1, 0, 0, 1 ], [ 1, 1, -1, 0, -1, 0 ], [ 1, 1, -1, 0, 0, -1 ], [ 0, 1, -1, 0, 0, 0 ] ], 4.375 ], - [ [ [ -1, 1, -1, 0, 0, 1 ], [ 1, 1, -1, 0, -1, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 4 ], - [ [ [ -1, 1, -1, 0, 0, 1 ], [ 1, 1, -1, 0, -1, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 0 ], - [ [ [ -1, 1, -1, 0, 0, 1 ], [ 0, 2, -1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 1, -1, 0, 0, 1 ], [ 0, 2, -1, 0, 0, 0 ], [ 1, 1, -1, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 3.75 ], - [ [ [ -1, 1, -1, 0, 0, 1 ], [ 0, 2, -1, 0, 0, 0 ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 2.25 ] - ], - [ - [ [ [ -1, 1, -1, 0, 0, 1 ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 1, -1, 1, 0, -1 ] ], 4.375 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ -1, 1, 0, 1, 0, 0 ] ], 2.5 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 0, -1, 1, 0, 0 ] ], 1.375 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ -1, 1, -1, 1, 1, 0 ] ], 3.75 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 1, -1, 1, -1, 0 ] ], 1.625 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ] ], 1.125 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 1, -2, 1, 0, 0 ] ], 5 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ -1, 1, -1, 1, 0, 1 ] ], 1.625 ] - ], - [ - [ [ [ -2, 1, -1, 2, 0, 0 ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ -1, 1, -1, 1, 0, 1 ] ], 0 ], - [ [ [ -2, 1, -1, 2, 0, 0 ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ -1, 1, -1, 2, 0, 0 ] ], 5 ], - [ [ [ -2, 1, -1, 2, 0, 0 ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 1, -1, 1, 0, -1 ] ], 2.125 ], - [ [ [ -2, 1, -1, 2, 0, 0 ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 0, -1, 1, 0, 0 ] ], 1.625 ] - ], - [ - [ [ [ -2, 1, -1, 2, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 0, -1, 1, 0, 0 ] ], 4.75 ], - [ [ [ -2, 1, -1, 2, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ 0, 1, -1, 1, 0, 0 ], [ -1, 3, -1, 0, 0, 0 ] ], 0 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ 0, 1, -1, 1, 0, 0 ], [ -1, 3, -1, 0, 0, 0 ] ], 0 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ 1, 2, -1, 0, 0, -1 ], [ -1, 3, -1, 0, 0, 0 ] ], 4 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ 1, 2, -1, 0, 0, -1 ], [ 0, 2, -2, 0, 0, 0 ] ], 4 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ 1, 2, -1, 0, 0, -1 ], [ -1, 2, -1, 0, 0, 1 ] ], 0 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ 1, 1, -1, 0, 0, 0 ], [ -1, 2, -1, 0, 0, 1 ] ], 2.75 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ 1, 1, -1, 0, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ] ], 4.625 ] - ], - [ - [ [ [ -1, 2, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 1, -1, 0, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ] ], 0 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 0 ], - [ [ [ -1, 2, -1, 1, 0, -1 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 4 ], - [ [ [ -2, 2, 0, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 4.75 ], - [ [ [ -1, 1, -1, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 3.25 ], - [ [ [ -2, 2, -1, 1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 3.75 ], - [ [ [ -1, 2, -1, 1, -1, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 4.125 ], - [ [ [ -2, 3, -1, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 2.625 ], - [ [ [ -3, 2, -1, 1, 0, 1 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 4.5 ], - [ [ [ -2, 2, -2, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 2.625 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 3.375 ] - ], - [ - [ [ [ -3, 3, -1, 1, 0, 0 ], [ -1, 3, -1, 1, -1, 0 ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 0 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ -1, 3, -1, 1, -1, 0 ], [ -1, 3, -1, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ] ], 0 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ -1, 3, -1, 1, -1, 0 ], [ -1, 3, -1, 1, 0, 0 ], [ -2, 3, 0, 1, 0, 0 ] ], 4.5 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ -1, 3, -1, 1, -1, 0 ], [ -1, 3, -1, 1, 0, 0 ], [ -1, 3, -1, 1, 0, -1 ] ], 0 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ -1, 3, -1, 1, -1, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -1, 3, -1, 1, 0, -1 ] ], 0 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ -2, 4, -1, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -1, 3, -1, 1, 0, -1 ] ], 4.5 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ -2, 4, -1, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -2, 3, -1, 2, 0, 0 ] ], 4.875 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ -2, 4, -1, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -3, 3, -1, 2, 0, 0 ] ], 4.25 ] - ], - [ - [ [ [ -3, 3, -1, 1, 0, 0 ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ], [ -3, 3, -1, 2, 0, 0 ] ], 0 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -3, 3, -1, 2, 0, 0 ] ], 0 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -3, 3, -1, 1, 0, 1 ] ], 2.125 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -3, 4, -1, 1, 0, 0 ] ], 2 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -2, 3, -2, 1, 0, 0 ] ], 1.125 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -2, 3, -1, 1, 0, 0 ] ], 0.875 ] - ], - [ - [ [ [ -3, 3, -1, 1, 0, 0 ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ], [ -2, 3, -1, 1, 0, 0 ] ], 1.875 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ], [ -1, 2, -2, 1, 0, 0 ] ], 0 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -1, 2, -2, 1, 0, 0 ] ], 0 ], - [ [ [ -2, 2, -2, 1, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -1, 2, -2, 1, 0, 0 ] ], 4.375 ], - [ [ [ -3, 2, -1, 1, 0, 1 ], [ 0, 2, -1, 0, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -1, 2, -2, 1, 0, 0 ] ], 4.375 ], - [ [ [ -3, 2, -1, 1, 0, 1 ], [ 0, 2, -1, 0, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ 0, 2, -1, 0, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ 0, 2, -1, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 9.625 ] - ] - ] -], -"last_changes": -[ - [ [ -3, 3, -1, 1, 0, 0 ], [ -2, 4, -1, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -2, 3, -1, 1, 0, 0 ] ], - [ [ -3, 3, -1, 1, 0, 0 ], [ -2, 4, -1, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -1, 2, -2, 1, 0, 0 ] ], - [ [ -3, 3, -1, 1, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -1, 2, -2, 1, 0, 0 ] ], - [ [ -2, 2, -2, 1, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -1, 2, -2, 1, 0, 0 ] ], - [ [ -3, 2, -1, 1, 0, 1 ], [ 0, 2, -1, 0, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -1, 2, -2, 1, 0, 0 ] ] -], -"cur_uid": "6a7a8dd9", -"ref_uid": "63bf7942", -"order_seed": 327691, -"dur_seed": 667550, -"motifs_seed": 549585, -"entrances_probs_vals": [ 1, 0, 0, 0.88, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 0, 0.88, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 0, 0.88, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 3 ], [ 2, 0, 1, 2, 2, 2, 1, 2, 2 ], [ ] ], - [ [ 2 ], [ 3, 3, 3, 3, 3, 3, 3, 3 ], [ 1, 0 ] ], - [ [ 2 ], [ 0, 3, 3, 3 ], [ 1 ] ], - [ [ 1 ], [ 3, 0, 2, 3, 3, 2, 3 ], [ ] ], - [ [ 3 ], [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 1, 2 ] ], - [ [ 0 ], [ 1, 2, 3, 3, 2, 1, 3, 3 ], [ ] ], - [ [ 0 ], [ 3, 3, 3, 3 ], [ 1, 2 ] ], - [ [ 2 ], [ 3, 1, 0, 0 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/71add9fc/71add9fc_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/71add9fc/71add9fc_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/71add9fc/71add9fc_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/71add9fc/71add9fc_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/71add9fc/71add9fc_mus_model.json deleted file mode 100644 index ab65a8d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/71add9fc/71add9fc_mus_model.json +++ /dev/null @@ -1,210 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 4.875 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 0, 1, 0, 0, 0 ] ], 4.75 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 4.125 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 1 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 4.875 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 1 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, -1, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 1 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, -1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, -1, 0, 0, 0 ] ], 4.125 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ -1, 1, 0, 0, 0, 1 ] ], 0 ], - [ [ [ -1, 1, 1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ -1, 1, 0, 0, 0, 1 ] ], 0 ], - [ [ [ -1, 1, 1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 1 ] ], 4.875 ] - ], - [ - [ [ [ -1, 1, 1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ], [ -1, 1, 0, 1, 0, 0 ] ], 0 ], - [ [ [ 0, 1, 0, 0, 0, -1 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ], [ -1, 1, 0, 1, 0, 0 ] ], 0 ], - [ [ [ 0, 1, 0, 0, 0, -1 ], [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 1 ], [ -1, 1, 0, 1, 0, 0 ] ], 4 ] - ], - [ - [ [ [ 0, 1, 0, 0, 0, -1 ], [ 0, 1, 0, 0, 1, 0 ], [ -1, 1, 0, 0, 0, 1 ], [ -1, 1, 0, 1, 0, 0 ] ], 3.75 ], - [ [ [ 0, 1, 0, 0, 0, -1 ], [ 0, 1, 0, 0, 1, 0 ], [ -1, 1, 0, 0, 0, 1 ], [ 0, 1, 0, 0, 1, -1 ] ], 0 ], - [ [ [ 0, 1, 0, 0, 0, -1 ], [ 0, 1, 0, 0, 1, 0 ], [ -1, 1, 1, 0, 1, 0 ], [ 0, 1, 0, 0, 1, -1 ] ], 0 ], - [ [ [ 0, 1, 0, 0, 0, -1 ], [ -1, 1, 0, 1, 1, 0 ], [ -1, 1, 1, 0, 1, 0 ], [ 0, 1, 0, 0, 1, -1 ] ], 4.25 ] - ], - [ - [ [ [ 0, 1, 0, 0, 0, -1 ], [ -1, 1, 0, 1, 1, 0 ], [ -1, 1, 1, 0, 1, 0 ], [ -2, 2, 0, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 1, 0 ], [ -1, 1, 1, 0, 1, 0 ], [ -2, 2, 0, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 1, 2, 0 ], [ -2, 2, 0, 1, 1, 0 ] ], 4.625 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 1, 2, 0 ], [ -1, 1, 0, 1, 0, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 0, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 0, 0 ] ], 4.625 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ], [ -2, 1, 0, 1, 2, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ -1, 1, 0, 1, 1, -1 ], [ -2, 1, 0, 1, 2, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 1, 1, 1 ], [ -1, 1, 0, 1, 1, -1 ], [ -2, 1, 0, 1, 2, 0 ] ], 4.875 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 1, 1, 1 ], [ -1, 1, 0, 0, 1, 0 ], [ -2, 1, 0, 1, 2, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 1, 1, 1 ], [ -1, 1, 0, 0, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, -1, 1, 1, 0 ], [ -1, 1, 0, 0, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ] ], 4.125 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, -1, 1, 1, 0 ], [ 0, 1, 0, 1, 0, 0 ], [ -1, 0, 0, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, -1, 1, 1, 0 ], [ 0, 1, 0, 1, 0, 0 ], [ -2, 1, 1, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 2, 0, 1, 1, 0 ], [ 0, 1, 0, 1, 0, 0 ], [ -2, 1, 1, 1, 1, 0 ] ], 4 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 0, 0 ], [ 0, 1, 0, 1, 0, 0 ], [ -2, 1, 1, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 0, 0 ], [ 0, 1, 0, 1, 0, 0 ], [ -1, 1, 0, 1, 1, -1 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 0, 0 ], [ -1, 1, 0, 1, 2, 0 ], [ -1, 1, 0, 1, 1, -1 ] ], 4.25 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 0, 0 ], [ 0, 0, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 1, -1 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 0, 0 ], [ 0, 0, 0, 1, 1, 0 ], [ -1, 1, 0, 0, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 2, 0, 1, 1, 0 ], [ 0, 0, 0, 1, 1, 0 ], [ -1, 1, 0, 0, 1, 0 ] ], 4 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 2, 0, 1, 1, 0 ], [ 0, 1, 0, 1, 1, -1 ], [ -1, 1, 0, 0, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 2, 0, 1, 1, 0 ], [ 0, 1, 0, 1, 1, -1 ], [ -2, 1, 0, 2, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, -1, 1, 1, 0 ], [ 0, 1, 0, 1, 1, -1 ], [ -2, 1, 0, 2, 1, 0 ] ], 4.375 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 1, 1, 1 ], [ 0, 1, 0, 1, 1, -1 ], [ -2, 1, 0, 2, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 1, 1, 1 ], [ -1, 1, 1, 1, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 1, 1, 1 ], [ -1, 1, 1, 1, 1, 0 ], [ -1, 1, 0, 1, 1, -1 ] ], 4 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 1, 1, 1 ], [ 0, 0, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 1, -1 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 1, 1, 1 ], [ 0, 0, 0, 1, 1, 0 ], [ -2, 1, 1, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 2, 0, 1, 1, 0 ], [ 0, 0, 0, 1, 1, 0 ], [ -2, 1, 1, 1, 1, 0 ] ], 4.625 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 2, 0, 1, 1, 0 ], [ 0, 0, 0, 1, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, -1, 1, 1, 0 ], [ 0, 0, 0, 1, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, -1, 1, 1, 0 ], [ -1, 1, 0, 1, 2, 0 ], [ -1, 0, 0, 1, 1, 0 ] ], 4.625 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, -1, 1, 1, 0 ], [ 0, 1, 0, 1, 0, 0 ], [ -1, 0, 0, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 1, 1, 1 ], [ 0, 1, 0, 1, 0, 0 ], [ -1, 0, 0, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 1, 1, 1 ], [ 0, 1, 0, 1, 0, 0 ], [ -2, 1, 0, 1, 2, 0 ] ], 4.5 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ 0, 1, 0, 1, 0, 0 ], [ -2, 1, 0, 1, 2, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ 0, 0, 0, 1, 1, 0 ], [ -2, 1, 0, 1, 2, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ 0, 0, 0, 1, 1, 0 ], [ -2, 2, 0, 1, 1, 0 ] ], 4.375 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ 0, 0, 0, 1, 1, 0 ], [ -1, 1, -1, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 1, -1 ], [ 0, 0, 0, 1, 1, 0 ], [ -1, 1, -1, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 1, -1 ], [ -1, 1, 1, 1, 1, 0 ], [ -1, 1, -1, 1, 1, 0 ] ], 4.125 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 1, -1 ], [ -1, 1, 1, 1, 1, 0 ], [ -2, 1, 0, 1, 1, 1 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 0, 1, 0 ], [ -1, 1, 1, 1, 1, 0 ], [ -2, 1, 0, 1, 1, 1 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 0, 1, 0 ], [ 0, 1, 0, 1, 1, -1 ], [ -2, 1, 0, 1, 1, 1 ] ], 4.5 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 0, 1, 0 ], [ 0, 1, 0, 1, 1, -1 ], [ -2, 2, 0, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 0, 1, 0 ], [ -1, 1, 0, 1, 2, 0 ], [ -2, 2, 0, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 2, 0 ], [ -2, 2, 0, 1, 1, 0 ] ], 3.875 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 0, 0 ], [ -1, 1, 0, 1, 2, 0 ], [ -2, 2, 0, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 0, 0 ], [ -1, 1, 0, 1, 2, 0 ], [ -1, 1, -1, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 0, 0 ], [ 0, 0, 0, 1, 1, 0 ], [ -1, 1, -1, 1, 1, 0 ] ], 3.75 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 0, 0 ], [ 0, 1, 0, 1, 1, -1 ], [ -1, 1, -1, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 1, 0, 1, 0, 0 ], [ 0, 1, 0, 1, 1, -1 ], [ -2, 1, 0, 1, 1, 1 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 2, 0, 1, 1, 0 ], [ 0, 1, 0, 1, 1, -1 ], [ -2, 1, 0, 1, 1, 1 ] ], 4.5 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 2, 0, 1, 1, 0 ], [ -1, 1, 1, 1, 1, 0 ], [ -2, 1, 0, 1, 1, 1 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 1, 1, 1, 0 ], [ -1, 1, 1, 1, 1, 0 ], [ -2, 1, 0, 1, 1, 1 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 1, 1, 1, 0 ], [ -1, 1, 1, 1, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ] ], 4.75 ] - ], - [ - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ], [ -1, 1, 1, 1, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ], [ -1, 1, 1, 1, 1, 0 ], [ 0, 0, 0, 1, 1, 0 ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ], [ 0, 1, 0, 1, 1, -1 ], [ 0, 0, 0, 1, 1, 0 ] ], 4.75 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ], [ 0, 1, 0, 1, 1, -1 ], [ "Rest" ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ "Rest" ], [ 0, 1, 0, 1, 1, -1 ], [ "Rest" ] ], 0 ], - [ [ [ -2, 1, 0, 1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 5.25 ] - ] - ] -], -"last_changes": -[ - [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 1, 1, 1, 0 ], [ -1, 1, 1, 1, 1, 0 ], [ -2, 1, 0, 1, 1, 1 ] ], - [ [ -2, 1, 0, 1, 1, 0 ], [ -2, 1, 1, 1, 1, 0 ], [ -1, 1, 1, 1, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ] ], - [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ], [ -1, 1, 1, 1, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ] ], - [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ], [ -1, 1, 1, 1, 1, 0 ], [ 0, 0, 0, 1, 1, 0 ] ], - [ [ -2, 1, 0, 1, 1, 0 ], [ -1, 0, 0, 1, 1, 0 ], [ 0, 1, 0, 1, 1, -1 ], [ 0, 0, 0, 1, 1, 0 ] ] -], -"cur_uid": "71add9fc", -"ref_uid": "nil", -"order_seed": 921767, -"dur_seed": 954688, -"motifs_seed": 995213, -"entrances_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 1 ], [ 3, 2, 1 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 1, 2, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 1, 2, 3 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/72dc057f_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/72dc057f_code.scd deleted file mode 100644 index 57e638d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/72dc057f_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/72dc057f_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/72dc057f_mus_model.json deleted file mode 100644 index 5541d17..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/72dc057f_mus_model.json +++ /dev/null @@ -1,59 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 5 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ -1, 3, -2, -1, 2, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ], [ -1, 3, -2, -1, 2, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 6.875 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ], [ -1, 3, -1, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ -1, 3, -1, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ -1, 3, -1, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ] ], 3.875 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ 0, 2, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ 0, 2, -2, -1, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -3, -1, 1, 0 ], [ 0, 2, -2, -1, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ] ], 6.125 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ 0, 2, -2, -1, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 6.125 ] - ] - ] -], -"last_changes": -[ - [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ -1, 3, -1, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ -1, 3, -1, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ 0, 2, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ 0, 2, -2, -1, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -3, -1, 1, 0 ], [ 0, 2, -2, -1, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ] ] -], -"cur_uid": "72dc057f", -"ref_uid": 62300302, -"order_seed": 209649, -"dur_seed": 795391, -"motifs_seed": 821280, -"entrances_probs_vals": [ 1, 0, 2.9365079365079, 0.47, 2.8021978021978, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 2.7380952380952, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 2.7380952380952, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ -1200, 1200, 0, 0, 0.35390946502058, 0, 0.5, 0.5, 0.62139917695473, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8.0714285714286, 10.091836734694 ], -"passages_size": [ 0, 10 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/lilypond/part_I.ly deleted file mode 100644 index 91049e5..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/lilypond/part_I.ly +++ /dev/null @@ -1,30 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2 e2^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e2. ~ e8.[ e16^\markup { \pad-markup #0.2 "-36"}] ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e2. ~ e8[ d8^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d2. ~ d8.[ r16] } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/lilypond/part_II.ly deleted file mode 100644 index 80a76d1..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/lilypond/part_II.ly +++ /dev/null @@ -1,30 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2 dis'2^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }} ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'2. ~ dis'8.[ cis'16^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'2. ~ cis'8[ d'8^\markup { \pad-markup #0.2 "+14"}] ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'2. ~ d'8.[ r16] } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/lilypond/part_III.ly deleted file mode 100644 index 0b76537..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/lilypond/part_III.ly +++ /dev/null @@ -1,30 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2 cis2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis2. ~ cis8.[ cis16^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis2. ~ cis8[ f8^\markup { \pad-markup #0.2 "+29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}] ~ } - \bar "|" - { f1 ~ } - \bar "|" - { f1 ~ } - \bar "|" - { f2. ~ f8.[ r16] } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/lilypond/part_IV.ly deleted file mode 100644 index e37440b..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/72dc057f/lilypond/part_IV.ly +++ /dev/null @@ -1,30 +0,0 @@ -{ - { a,1^\markup { \pad-markup #0.2 "+16"} ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,2. ~ a,8.[ r16] } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/74307bb4_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/74307bb4_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/74307bb4_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/74307bb4_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/74307bb4_mus_model.json deleted file mode 100644 index 6d6bd44..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/74307bb4_mus_model.json +++ /dev/null @@ -1,120 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 0, 0, 0 ] ], 3.875 ], - [ [ [ "Rest" ], [ "Rest" ], [ 1, 1, -1, -1, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 0 ], - [ [ [ -1, 1, -1, 0, 0, 1 ], [ "Rest" ], [ 1, 1, -1, -1, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 0 ], - [ [ [ -1, 1, -1, 0, 0, 1 ], [ 1, 1, -1, 0, -1, 0 ], [ 1, 1, -1, -1, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 4.25 ], - [ [ [ -1, 1, -1, 0, 0, 1 ], [ 1, 1, -1, 0, -1, 0 ], [ 1, 1, -1, 0, 0, -1 ], [ 0, 1, -1, 0, 0, 0 ] ], 4.375 ], - [ [ [ -1, 1, -1, 0, 0, 1 ], [ 1, 1, -1, 0, -1, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 4 ], - [ [ [ -1, 1, -1, 0, 0, 1 ], [ 1, 1, -1, 0, -1, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 0 ], - [ [ [ -1, 1, -1, 0, 0, 1 ], [ 0, 2, -1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 1, -1, 0, 0, 1 ], [ 0, 2, -1, 0, 0, 0 ], [ 1, 1, -1, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 3.75 ], - [ [ [ -1, 1, -1, 0, 0, 1 ], [ 0, 2, -1, 0, 0, 0 ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 2.25 ] - ], - [ - [ [ [ -1, 1, -1, 0, 0, 1 ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 1, -1, 1, 0, -1 ] ], 4.375 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ -1, 1, 0, 1, 0, 0 ] ], 2.5 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 0, -1, 1, 0, 0 ] ], 1.375 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ -1, 1, -1, 1, 1, 0 ] ], 3.75 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 1, -1, 1, -1, 0 ] ], 1.625 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ] ], 1.125 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 1, -2, 1, 0, 0 ] ], 5 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ -1, 1, -1, 1, 0, 1 ] ], 1.625 ] - ], - [ - [ [ [ -2, 1, -1, 2, 0, 0 ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ -1, 1, -1, 1, 0, 1 ] ], 0 ], - [ [ [ -2, 1, -1, 2, 0, 0 ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ -1, 1, -1, 2, 0, 0 ] ], 5 ], - [ [ [ -2, 1, -1, 2, 0, 0 ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 1, -1, 1, 0, -1 ] ], 2.125 ], - [ [ [ -2, 1, -1, 2, 0, 0 ], [ "Rest" ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 0, -1, 1, 0, 0 ] ], 1.625 ] - ], - [ - [ [ [ -2, 1, -1, 2, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ 0, 1, -1, 1, 0, 0 ], [ 0, 0, -1, 1, 0, 0 ] ], 4.75 ], - [ [ [ -2, 1, -1, 2, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ 0, 1, -1, 1, 0, 0 ], [ -1, 3, -1, 0, 0, 0 ] ], 0 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ 0, 1, -1, 1, 0, 0 ], [ -1, 3, -1, 0, 0, 0 ] ], 0 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ 1, 2, -1, 0, 0, -1 ], [ -1, 3, -1, 0, 0, 0 ] ], 4 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ 1, 2, -1, 0, 0, -1 ], [ 0, 2, -2, 0, 0, 0 ] ], 4 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ 1, 2, -1, 0, 0, -1 ], [ -1, 2, -1, 0, 0, 1 ] ], 0 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ 1, 1, -1, 0, 0, 0 ], [ -1, 2, -1, 0, 0, 1 ] ], 2.75 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ 1, 1, -1, 0, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ] ], 4.625 ] - ], - [ - [ [ [ -1, 2, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 1, -1, 0, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ] ], 0 ], - [ [ [ -1, 2, -1, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 0 ], - [ [ [ -1, 2, -1, 1, 0, -1 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 4 ], - [ [ [ -2, 2, 0, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 4.75 ], - [ [ [ -1, 1, -1, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 3.25 ], - [ [ [ -2, 2, -1, 1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 3.75 ], - [ [ [ -1, 2, -1, 1, -1, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 4.125 ], - [ [ [ -2, 3, -1, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 2.625 ], - [ [ [ -3, 2, -1, 1, 0, 1 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 4.5 ], - [ [ [ -2, 2, -2, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 2.625 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 3.375 ] - ], - [ - [ [ [ -3, 3, -1, 1, 0, 0 ], [ -1, 3, -1, 1, -1, 0 ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ] ], 0 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ -1, 3, -1, 1, -1, 0 ], [ -1, 3, -1, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ] ], 0 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ -1, 3, -1, 1, -1, 0 ], [ -1, 3, -1, 1, 0, 0 ], [ -2, 3, 0, 1, 0, 0 ] ], 4.5 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ -1, 3, -1, 1, -1, 0 ], [ -1, 3, -1, 1, 0, 0 ], [ -1, 3, -1, 1, 0, -1 ] ], 0 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ -1, 3, -1, 1, -1, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -1, 3, -1, 1, 0, -1 ] ], 0 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ -2, 4, -1, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -1, 3, -1, 1, 0, -1 ] ], 4.5 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ -2, 4, -1, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -2, 3, -1, 2, 0, 0 ] ], 4.875 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ -2, 4, -1, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -3, 3, -1, 2, 0, 0 ] ], 4.25 ] - ], - [ - [ [ [ -3, 3, -1, 1, 0, 0 ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ], [ -3, 3, -1, 2, 0, 0 ] ], 0 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -3, 3, -1, 2, 0, 0 ] ], 0 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -3, 3, -1, 1, 0, 1 ] ], 2.125 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -3, 4, -1, 1, 0, 0 ] ], 2 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -2, 3, -2, 1, 0, 0 ] ], 1.125 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ -2, 3, -1, 1, 0, 0 ] ], 0.875 ] - ], - [ - [ [ [ -3, 3, -1, 1, 0, 0 ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ], [ -2, 3, -1, 1, 0, 0 ] ], 1.875 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ "Rest" ], [ -1, 2, -1, 1, 0, 0 ], [ -1, 2, -2, 1, 0, 0 ] ], 0 ], - [ [ [ -3, 3, -1, 1, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -1, 2, -2, 1, 0, 0 ] ], 0 ], - [ [ [ -2, 2, -2, 1, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -1, 2, -2, 1, 0, 0 ] ], 4.375 ], - [ [ [ -3, 2, -1, 1, 0, 1 ], [ 0, 2, -1, 0, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -1, 2, -2, 1, 0, 0 ] ], 4.375 ], - [ [ [ -3, 2, -1, 1, 0, 1 ], [ 0, 2, -1, 0, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ 0, 2, -1, 0, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ 0, 2, -1, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ] -], -"cur_uid": "74307bb4", -"ref_uid": "77b0d2dc", -"order_seed": 921767, -"dur_seed": 954688, -"motifs_seed": 995213, -"entrances_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "true", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/lilypond/part_I.ly deleted file mode 100644 index 8b64a06..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/lilypond/part_I.ly +++ /dev/null @@ -1,142 +0,0 @@ -{ - { dis'1^\markup { \pad-markup #0.2 "+16"} ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'2. e'4^\markup { \pad-markup #0.2 "+44"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↓" }} ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'2. ~ e'8.[ f'16^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }}] ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'8.[ fis'16^\markup { \pad-markup #0.2 "-17"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }}] ~ fis'2 ~ fis'8[ fis'8^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↑" }}] ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'2. g'4^\markup { \pad-markup #0.2 "+33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↓" }} ~ } - \bar "|" - { g'2 ~ g'16[ gis'8.^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }}] ~ gis'4 ~ } - \bar "|" - { gis'8[ a'8^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }}] ~ a'2. ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'2 ~ a'8[ a'8^\markup { \pad-markup #0.2 "+25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }}] ~ a'4 ~ } - \bar "|" - { a'4 ~ a'8.[ b'16^\markup { \pad-markup #0.2 "-47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ b'2 ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'2. ~ b'8.[ e'16^\markup { \pad-markup #0.2 "+44"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↓" }}] ~ } - \bar "|" - { e'1 } - \bar "|" - { fis'1^\markup { \pad-markup #0.2 "-17"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }} ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'8.[ f'16^\markup { \pad-markup #0.2 "+20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }}] ~ f'2. ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'8.[ fis'16^\markup { \pad-markup #0.2 "+31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}] ~ fis'2. ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'8.[ g'16^\markup { \pad-markup #0.2 "-42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }}] ~ g'2. ~ } - \bar "|" - { g'2 ~ g'16[ gis'8.^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ gis'4 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'4 ~ gis'8[ g'8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ g'2 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'2 ~ g'8[ fis'8^\markup { \pad-markup #0.2 "+48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ fis'4 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'2. ~ fis'8[ cis''8^\markup { \pad-markup #0.2 "-43"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''4 ~ cis''16[ cis'8.^\markup { \pad-markup #0.2 "-43"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ cis'2 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'4 ~ cis'8.[ b16^\markup { \pad-markup #0.2 "+29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }}] ~ b2 ~ } - \bar "|" - { b2 ais2^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { ais2 b2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { b16[ dis'8.^\markup { \pad-markup #0.2 "-12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ dis'2. ~ } - \bar "|" - { dis'4 ~ dis'8.[ e'16^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }}] ~ e'2 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/lilypond/part_II.ly deleted file mode 100644 index 222dcb4..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/lilypond/part_II.ly +++ /dev/null @@ -1,142 +0,0 @@ -{ - { r1 } - \bar "|" - { r2. r8.[ f'16^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↓" }}] ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'16[ g'8.^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↓" }}] ~ g'2. ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'4 gis'2.^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }} ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'4 g'2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }} dis''4^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { dis''1 ~ } - \bar "|" - { dis''2 ~ dis''8[ cis''8^\markup { \pad-markup #0.2 "-16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }}] ~ cis''4 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''8.[ d''16^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ d''2. ~ } - \bar "|" - { d''1 ~ } - \bar "|" - { d''1 ~ } - \bar "|" - { d''1 ~ } - \bar "|" - { d''8.[ dis''16^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ dis''2. ~ } - \bar "|" - { dis''1 ~ } - \bar "|" - { dis''1 ~ } - \bar "|" - { dis''2. ~ dis''8[ r8] } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r4 r8[ dis''8^\markup { \pad-markup #0.2 "-12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ dis''2 ~ } - \bar "|" - { dis''1 ~ } - \bar "|" - { dis''2 ~ dis''8[ gis'8^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ gis'4 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'4 ~ gis'8.[ r16] r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2 gis'2^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/lilypond/part_III.ly deleted file mode 100644 index 0991a78..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/lilypond/part_III.ly +++ /dev/null @@ -1,142 +0,0 @@ -{ - { r1 } - \bar "|" - { r2. r8.[ ais'16^\markup { \pad-markup #0.2 "-36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }}] ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'4 ais'2.^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }} ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'2. r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r2. r16[ ais'8.^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'2. ~ ais'8[ r8] } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r4 r8[ a'8^\markup { \pad-markup #0.2 "+37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }}] ~ a'2 ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'2 ~ a'8[ ais'8^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ ais'4 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'4 ~ ais'8.[ r16] r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r4 r8.[ ais'16^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }}] ~ ais'2 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/lilypond/part_IV.ly deleted file mode 100644 index 0d3677b..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/74307bb4/lilypond/part_IV.ly +++ /dev/null @@ -1,142 +0,0 @@ -{ - { r1 } - \bar "|" - { r2. r8.[ c'16^\markup { \pad-markup #0.2 "-44"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }}] ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'2. r4 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r4 r8.[ b16^\markup { \pad-markup #0.2 "-47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}] ~ b2 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b8.[ ais16^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ ais2. ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais2. ~ ais8[ b8^\markup { \pad-markup #0.2 "+46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↓" }}] ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b2. ~ b8[ c'8^\markup { \pad-markup #0.2 "-27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }}] ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'4 cis'2.^\markup { \pad-markup #0.2 "-16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }} ~ } - \bar "|" - { cis'2. ~ cis'8[ cis'8^\markup { \pad-markup #0.2 "+38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }}] ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'2. d'4^\markup { \pad-markup #0.2 "+35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }} ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'2. ~ d'16[ dis'8.^\markup { \pad-markup #0.2 "-12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}] ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'8[ e8^\markup { \pad-markup #0.2 "+27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }}] ~ e2. ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e4 ~ e8[ e8^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }}] ~ e2 ~ } - \bar "|" - { e2 ~ e8.[ dis16^\markup { \pad-markup #0.2 "-12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}] ~ dis4 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis4 ~ dis8.[ e16^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ e2 ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e2 ~ e8[ e8^\markup { \pad-markup #0.2 "+27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }}] ~ e4 ~ } - \bar "|" - { e1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/74b8f8d9_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/74b8f8d9_code.scd deleted file mode 100644 index 57e638d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/74b8f8d9_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/74b8f8d9_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/74b8f8d9_mus_model.json deleted file mode 100644 index c472d47..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/74b8f8d9_mus_model.json +++ /dev/null @@ -1,77 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3.75 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ -2, 3, -1, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 4.75 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 2, -2, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 2, -2, -1, 1, 0 ], [ -1, 3, -3, -1, 1, 0 ] ], 7.125 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -2, 3, -2, -1, 2, 0 ], [ -1, 3, -3, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -2, 3, -2, -1, 2, 0 ], [ 0, 3, -2, -1, 1, -1 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ -2, 3, -2, -1, 2, 0 ], [ 0, 3, -2, -1, 1, -1 ] ], 4.5 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ], [ 0, 3, -2, -1, 1, -1 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ], [ -1, 3, -1, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ], [ -1, 3, -1, -1, 1, 0 ] ], 6.875 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ], [ -1, 3, -1, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ], [ -1, 3, -1, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ], [ 0, 2, -2, -1, 1, 0 ] ], 5.25 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ], [ -1, 3, -3, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 3, -3, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 3, -3, -1, 1, 0 ] ], 6.125 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ -1, 2, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ -1, 2, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 10.125 ] - ] - ] -], -"last_changes": -[ - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ], [ -1, 3, -1, -1, 1, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ], [ 0, 2, -2, -1, 1, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ], [ -1, 3, -3, -1, 1, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 3, -3, -1, 1, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 3, -3, -1, 1, 0 ] ] -], -"cur_uid": "74b8f8d9", -"ref_uid": "4c059f33", -"order_seed": 824152, -"dur_seed": 266394, -"motifs_seed": 206072, -"entrances_probs_vals": [ 1, 0, 5.0793650793651, 0.47, 2.8021978021978, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 2.7380952380952, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 2.7380952380952, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8.0714285714286, 10.091836734694 ], -"passages_size": [ 0, 10 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/lilypond/part_I.ly deleted file mode 100644 index 2d48723..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/lilypond/part_I.ly +++ /dev/null @@ -1,50 +0,0 @@ -{ - { r1 } - \bar "|" - { r2. r8[ e8^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e4 f2.^\markup { \pad-markup #0.2 "+29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { f1 ~ } - \bar "|" - { f1 ~ } - \bar "|" - { f2. ~ f16[ cis'8.^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'16[ cis'8.^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ cis'2. ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'2 d'2^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'8[ f8^\markup { \pad-markup #0.2 "+29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}] ~ f2. ~ } - \bar "|" - { f1 ~ } - \bar "|" - { f1 ~ } - \bar "|" - { f8.[ r16] r2. } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/lilypond/part_II.ly deleted file mode 100644 index 1c284cd..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/lilypond/part_II.ly +++ /dev/null @@ -1,50 +0,0 @@ -{ - { r1 } - \bar "|" - { r2. r8[ cis8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis4 d2.^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d2. ~ d16[ dis8.^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }}] ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis16[ e8.^\markup { \pad-markup #0.2 "-36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }}] ~ e2. ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e2 e2^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e8[ fis8^\markup { \pad-markup #0.2 "-44"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }}] ~ fis2. ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis8.[ r16] r2. } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/lilypond/part_III.ly deleted file mode 100644 index ecf1ce2..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/lilypond/part_III.ly +++ /dev/null @@ -1,50 +0,0 @@ -{ - { r1 } - \bar "|" - { r2. r8[ a8^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a4 fis2.^\markup { \pad-markup #0.2 "-44"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }} ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis2. ~ fis16[ g8.^\markup { \pad-markup #0.2 "-15"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g16[ a8.^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ a2. ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a2 cis2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis8[ d8^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ d2. ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d8.[ r16] r2. } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/lilypond/part_IV.ly deleted file mode 100644 index eca3efa..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/74b8f8d9/lilypond/part_IV.ly +++ /dev/null @@ -1,50 +0,0 @@ -{ - { a,1^\markup { \pad-markup #0.2 "+16"} ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,8.[ r16] r2. } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/76e45e56_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/76e45e56_code.scd deleted file mode 100644 index 57e638d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/76e45e56_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/76e45e56_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/76e45e56_mus_model.json deleted file mode 100644 index e1d66b2..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/76e45e56_mus_model.json +++ /dev/null @@ -1,71 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ -1, 3, -2, -1, 2, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ], [ -1, 3, -2, -1, 2, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 7 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ], [ -1, 3, -1, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ -1, 3, -1, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ -1, 3, -1, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ] ], 5.5 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ 0, 2, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ 0, 2, -2, -1, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -3, -1, 1, 0 ], [ 0, 2, -2, -1, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ] ], 4 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -3, -1, 1, 0 ], [ 0, 3, -2, -2, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -3, -1, 1, 0 ], [ 0, 3, -2, -2, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ 0, 3, -2, -2, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ] ], 5.625 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ] ], 6.5 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ "Rest" ], [ -1, 3, -2, -1, 1, -1 ] ], 0 ], - [ [ [ "Rest" ], [ -2, 3, -2, 0, 1, 0 ], [ "Rest" ], [ -1, 3, -2, -1, 1, -1 ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ -1, 3, -2, -1, 1, -1 ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 6.375 ] - ] - ] -], -"last_changes": -[ - [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -3, -1, 1, 0 ], [ 0, 3, -2, -2, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ 0, 3, -2, -2, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ] ] -], -"cur_uid": "76e45e56", -"ref_uid": 62300302, -"order_seed": 209649, -"dur_seed": 306774, -"motifs_seed": 821280, -"entrances_probs_vals": [ 1, 0, 2.9365079365079, 0.47, 2.8021978021978, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 2.7380952380952, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 2.7380952380952, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ -1200, 1200, 0, 0, 0.35390946502058, 0, 0.5, 0.5, 0.62139917695473, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8.0714285714286, 10.091836734694 ], -"passages_size": [ 0, 10 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/lilypond/part_I.ly deleted file mode 100644 index 7efbb7f..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/lilypond/part_I.ly +++ /dev/null @@ -1,38 +0,0 @@ -{ - { r2 e2^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 } - \bar "|" - { e1^\markup { \pad-markup #0.2 "-36"} ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e2. d4^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d2. cis4^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis2 ~ cis16[ cis8.^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ cis4 ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis2. ~ cis16[ r8.] } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/lilypond/part_II.ly deleted file mode 100644 index 36f4169..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/lilypond/part_II.ly +++ /dev/null @@ -1,38 +0,0 @@ -{ - { r2 dis'2^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }} ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 } - \bar "|" - { cis'1^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'2. d'4^\markup { \pad-markup #0.2 "+14"} ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'2. b4^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }} ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b2 ~ b16[ a8.^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ a4 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a2. ~ a16[ r8.] } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/lilypond/part_III.ly deleted file mode 100644 index 9a96093..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/lilypond/part_III.ly +++ /dev/null @@ -1,38 +0,0 @@ -{ - { r2 cis2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis1 } - \bar "|" - { cis1^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }} ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis2. f4^\markup { \pad-markup #0.2 "+29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { f1 ~ } - \bar "|" - { f2. fis4^\markup { \pad-markup #0.2 "-44"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }} ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis2 ~ fis16[ g8.^\markup { \pad-markup #0.2 "-15"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}] ~ g4 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g2. ~ g16[ r8.] } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/lilypond/part_IV.ly deleted file mode 100644 index c9189fc..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/76e45e56/lilypond/part_IV.ly +++ /dev/null @@ -1,38 +0,0 @@ -{ - { a,1^\markup { \pad-markup #0.2 "+16"} ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,2. ~ a,16[ r8.] } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/77b0d2dc/77b0d2dc_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/77b0d2dc/77b0d2dc_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/77b0d2dc/77b0d2dc_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/77b0d2dc/77b0d2dc_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/77b0d2dc/77b0d2dc_mus_model.json deleted file mode 100644 index 6f0561e..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/77b0d2dc/77b0d2dc_mus_model.json +++ /dev/null @@ -1,59 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 4.875 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 0, 1, 0, 0, 0 ] ], 4.75 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 4.125 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 9.625 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 0, 1, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ] -], -"cur_uid": "77b0d2dc", -"ref_uid": "nil", -"order_seed": 921767, -"dur_seed": 954688, -"motifs_seed": 995213, -"entrances_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/7bb0e931/7bb0e931_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/7bb0e931/7bb0e931_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/7bb0e931/7bb0e931_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/7bb0e931/7bb0e931_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/7bb0e931/7bb0e931_mus_model.json deleted file mode 100644 index 97c68b2..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/7bb0e931/7bb0e931_mus_model.json +++ /dev/null @@ -1,69 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 3.375 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 0, 1, 0, 0, 0 ] ], 1.25 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 3.125 ] - ], - [ - [ [ [ 1, 0, -1, 0, 0, -1 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ 1, 0, -1, 0, 0, -1 ], [ 1, 0, 1, 0, 0, -1 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 2.25 ] - ], - [ - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 1, 0, 1, 0, 0, -1 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 2.625 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ] ], 0 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ 2, -1, 0, -1, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 10.0 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 1, 0, -1, 0, 0, -1 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 1, 0, -1, 0, 0, -1 ], [ 1, 0, 1, 0, 0, -1 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 1, -1, 0, 0, -1, 0 ], [ 1, 0, 1, 0, 0, -1 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 1, -1, 0, 0, -1, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ] -], -"cur_uid": "7bb0e931", -"ref_uid": "nil", -"order_seed": 921767, -"dur_seed": 233566, -"motifs_seed": 995213, -"entrances_probs_vals": [ 1, 0, 0, 0.88, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 0, 0.88, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 0, 0.88, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 3, 2 ], [ 0, 1 ], [ ] ], - [ [ 3, 2 ], [ 0, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/7df3df4c/7df3df4c_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/7df3df4c/7df3df4c_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/7df3df4c/7df3df4c_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/7df3df4c/7df3df4c_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/7df3df4c/7df3df4c_mus_model.json deleted file mode 100644 index e06a740..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/7df3df4c/7df3df4c_mus_model.json +++ /dev/null @@ -1,59 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3.875 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 1, 0, 0, -1, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, -1, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 1 ], [ 1, 0, 0, 0, -1, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 4.875 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 4.75 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 4.125 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 1, 0, 0, 0 ] ], 0 ], - [ [ [ "Rest" ], [ 1, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 1, 0, 0, 0 ] ], 0 ], - [ [ [ "Rest" ], [ 1, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 9.625 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ] -], -"cur_uid": "7df3df4c", -"ref_uid": "77b0d2dc", -"order_seed": 921767, -"dur_seed": 954688, -"motifs_seed": 995213, -"entrances_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/7fe1da13/7fe1da13_code.scd b/resources/resources_bak_2024_01_03/string_quartet_2/7fe1da13/7fe1da13_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/7fe1da13/7fe1da13_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/7fe1da13/7fe1da13_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/7fe1da13/7fe1da13_mus_model.json deleted file mode 100644 index 61971c6..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/7fe1da13/7fe1da13_mus_model.json +++ /dev/null @@ -1,198 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 4.25 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 4.25 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 4.875 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 4.875 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 1, 0 ], [ -1, 0, 0, 1, 0, 1 ] ], 0 ], - [ [ [ 0, -1, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 1, 0 ], [ -1, 0, 0, 1, 0, 1 ] ], 0 ], - [ [ [ 0, -1, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 1 ], [ -1, 0, 0, 0, 0, 2 ], [ -1, 0, 0, 1, 0, 1 ] ], 3.875 ] - ], - [ - [ [ [ 0, -1, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 1 ], [ -1, 0, 0, 0, 0, 2 ], [ 0, 0, 0, 0, 1, 1 ] ], 0 ], - [ [ [ -1, 0, 1, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 1 ], [ -1, 0, 0, 0, 0, 2 ], [ 0, 0, 0, 0, 1, 1 ] ], 0 ], - [ [ [ -1, 0, 1, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 1 ], [ -1, 1, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 1, 1 ] ], 4.125 ] - ], - [ - [ [ [ -1, 0, 1, 0, 0, 1 ], [ -1, 0, 0, 1, 0, 1 ], [ -1, 1, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 1, 1 ] ], 4.875 ], - [ [ [ -1, 0, 1, 0, 0, 1 ], [ -1, 0, 0, 1, 0, 1 ], [ -1, 1, 0, 0, 0, 1 ], [ -1, 0, 0, 1, 0, 2 ] ], 0 ], - [ [ [ -1, 0, 1, 0, 0, 1 ], [ -1, 0, 0, 1, 0, 1 ], [ -2, 0, 0, 1, 0, 2 ], [ -1, 0, 0, 1, 0, 2 ] ], 0 ], - [ [ [ -1, 0, 1, 0, 0, 1 ], [ 0, 0, -1, 1, 0, 1 ], [ -2, 0, 0, 1, 0, 2 ], [ -1, 0, 0, 1, 0, 2 ] ], 4.375 ] - ], - [ - [ [ [ -1, 0, 1, 0, 0, 1 ], [ 0, 0, -1, 1, 0, 1 ], [ -2, 0, 0, 1, 0, 2 ], [ 0, -1, -1, 1, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ 0, 0, -1, 1, 0, 1 ], [ -2, 0, 0, 1, 0, 2 ], [ 0, -1, -1, 1, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ 0, 0, -1, 1, 0, 1 ], [ -1, 0, -1, 1, 0, 1 ], [ 0, -1, -1, 1, 0, 1 ] ], 3.875 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ 0, 0, -1, 1, 0, 1 ], [ -1, 0, -1, 1, 0, 1 ], [ -2, 0, -1, 2, 0, 2 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ 0, 0, -1, 1, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ -2, 0, -1, 2, 0, 2 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 1, -1, 2, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ -2, 0, -1, 2, 0, 2 ] ], 4.875 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 1, -1, 2, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ -1, 0, -2, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 1, -1, 2, 0, 1 ], [ -2, 0, 0, 2, 0, 1 ], [ -1, 0, -2, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -1, 2, -1, 1 ], [ -2, 0, 0, 2, 0, 1 ], [ -1, 0, -2, 2, 0, 1 ] ], 4.125 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -1, 2, -1, 1 ], [ -1, -1, -1, 2, 0, 1 ], [ -1, 0, -2, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -1, 2, -1, 1 ], [ -1, -1, -1, 2, 0, 1 ], [ -2, 1, -1, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 2, 1, 1 ], [ -1, -1, -1, 2, 0, 1 ], [ -2, 1, -1, 2, 0, 1 ] ], 4.75 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 2, 1, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ -2, 1, -1, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 2, 1, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ -1, 0, -1, 2, -1, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, -1, -1, 2, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ -1, 0, -1, 2, -1, 1 ] ], 4.875 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, 0, 2, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ -1, 0, -1, 2, -1, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, 0, 2, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ -2, 0, -1, 2, 1, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, 0, 2, 0, 1 ], [ -1, -1, -1, 2, 0, 1 ], [ -2, 0, -1, 2, 1, 1 ] ], 4.375 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, 0, 2, 0, 1 ], [ -1, 0, -1, 2, -1, 1 ], [ -2, 0, -1, 2, 1, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, 0, 2, 0, 1 ], [ -1, 0, -1, 2, -1, 1 ], [ -1, -1, -1, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ -1, 0, -1, 2, -1, 1 ], [ -1, -1, -1, 2, 0, 1 ] ], 5 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ -2, 1, -1, 2, 0, 1 ], [ -1, -1, -1, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ -2, 1, -1, 2, 0, 1 ], [ -2, 0, 0, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, -1, -1, 2, 0, 1 ], [ -2, 1, -1, 2, 0, 1 ], [ -2, 0, 0, 2, 0, 1 ] ], 4.25 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 2, 1, 1 ], [ -2, 1, -1, 2, 0, 1 ], [ -2, 0, 0, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 2, 1, 1 ], [ -1, 0, -2, 2, 0, 1 ], [ -2, 0, 0, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 2, 1, 1 ], [ -1, 0, -2, 2, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ] ], 3.875 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 2, 1, 1 ], [ -2, 0, -1, 2, 0, 2 ], [ -1, 0, -1, 2, 0, 0 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 2, 1, 1 ], [ -2, 0, -1, 2, 0, 2 ], [ -1, 0, -1, 1, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, -1, -1, 2, 0, 1 ], [ -2, 0, -1, 2, 0, 2 ], [ -1, 0, -1, 1, 0, 1 ] ], 4.375 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, -1, -1, 2, 0, 1 ], [ -2, 0, -1, 2, 0, 2 ], [ -1, 0, -2, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ -2, 0, -1, 2, 0, 2 ], [ -1, 0, -2, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ -2, 1, -1, 2, 0, 1 ], [ -1, 0, -2, 2, 0, 1 ] ], 4.375 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ -1, 0, -1, 2, -1, 1 ], [ -1, 0, -2, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -1, 1, 0, 1 ], [ -1, 0, -1, 2, -1, 1 ], [ -1, 0, -2, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -1, 1, 0, 1 ], [ -1, 0, -1, 2, -1, 1 ], [ -2, 1, -1, 2, 0, 1 ] ], 4.125 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, 0, 2, 0, 1 ], [ -1, 0, -1, 2, -1, 1 ], [ -2, 1, -1, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, 0, 2, 0, 1 ], [ -2, 0, -1, 2, 1, 1 ], [ -2, 1, -1, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, 0, 2, 0, 1 ], [ -2, 0, -1, 2, 1, 1 ], [ -1, 0, -1, 2, -1, 1 ] ], 3.875 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, 0, 2, 0, 1 ], [ -2, 0, -1, 2, 1, 1 ], [ 0, 0, -1, 1, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ -2, 0, -1, 2, 1, 1 ], [ 0, 0, -1, 1, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ -1, -1, -1, 2, 0, 1 ], [ 0, 0, -1, 1, 0, 1 ] ], 4.5 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ -1, -1, -1, 2, 0, 1 ], [ 0, 0, -1, 2, 0, 0 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -1, 1, 0, 1 ], [ -1, -1, -1, 2, 0, 1 ], [ 0, 0, -1, 2, 0, 0 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -1, 1, 0, 1 ], [ -2, 0, 0, 2, 0, 1 ], [ 0, 0, -1, 2, 0, 0 ] ], 4.625 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -1, 1, 0, 1 ], [ -2, 0, 0, 2, 0, 1 ], [ 0, -1, -1, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -1, 1, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ 0, -1, -1, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 2, 0, 2 ], [ -1, 0, -1, 2, 0, 0 ], [ 0, -1, -1, 2, 0, 1 ] ], 4.875 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -2, 2, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ 0, -1, -1, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -2, 2, 0, 1 ], [ -1, 0, -1, 2, 0, 0 ], [ -1, 0, 0, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -2, 2, 0, 1 ], [ -1, -1, -1, 2, 0, 1 ], [ -1, 0, 0, 2, 0, 1 ] ], 4.25 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -2, 2, 0, 1 ], [ -2, 0, -1, 2, 1, 1 ], [ -1, 0, 0, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -1, 0, -2, 2, 0, 1 ], [ -2, 0, -1, 2, 1, 1 ], [ 0, 0, -1, 2, 0, 0 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 1, -1, 2, 0, 1 ], [ -2, 0, -1, 2, 1, 1 ], [ 0, 0, -1, 2, 0, 0 ] ], 4.875 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 1, -1, 2, 0, 1 ], [ -1, 0, -1, 2, -1, 1 ], [ 0, 0, -1, 2, 0, 0 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 2, 0, 2 ], [ -1, 0, -1, 2, -1, 1 ], [ 0, 0, -1, 2, 0, 0 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 2, 0, 2 ], [ -1, 0, -1, 2, -1, 1 ], [ 0, 0, -1, 1, 0, 1 ] ], 4.5 ] - ], - [ - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 3, 0, 1 ], [ -1, 0, -1, 2, -1, 1 ], [ 0, 0, -1, 1, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 3, 0, 1 ], [ -1, 0, -1, 2, -1, 1 ], [ -2, 0, 0, 2, 0, 1 ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 3, 0, 1 ], [ -2, 1, -1, 2, 0, 1 ], [ -2, 0, 0, 2, 0, 1 ] ], 3.875 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 3, 0, 1 ], [ -2, 1, -1, 2, 0, 1 ], [ "Rest" ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 3, 0, 1 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ -2, 0, -1, 2, 0, 1 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 8.5 ] - ] - ] -], -"last_changes": -[ - [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 2, 0, 2 ], [ -1, 0, -1, 2, -1, 1 ], [ 0, 0, -1, 2, 0, 0 ] ], - [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 2, 0, 2 ], [ -1, 0, -1, 2, -1, 1 ], [ 0, 0, -1, 1, 0, 1 ] ], - [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 3, 0, 1 ], [ -1, 0, -1, 2, -1, 1 ], [ 0, 0, -1, 1, 0, 1 ] ], - [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 3, 0, 1 ], [ -1, 0, -1, 2, -1, 1 ], [ -2, 0, 0, 2, 0, 1 ] ], - [ [ -2, 0, -1, 2, 0, 1 ], [ -2, 0, -1, 3, 0, 1 ], [ -2, 1, -1, 2, 0, 1 ], [ -2, 0, 0, 2, 0, 1 ] ] -], -"cur_uid": "7fe1da13", -"ref_uid": "nil", -"order_seed": 962045, -"dur_seed": 299387, -"motifs_seed": 678579, -"entrances_probs_vals": [ 1, 0, 0, 3.8461538461538, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 0, 3.8461538461538, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 0, 3.8461538461538, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 1 ], [ 3, 2, 1 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 1, 2, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 1, 2, 3 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_2/tmp/tmp_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_2/tmp/tmp_mus_model.json deleted file mode 100644 index d270a25..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_2/tmp/tmp_mus_model.json +++ /dev/null @@ -1,71 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ "Rest" ], [ -1, 3, -2, -1, 2, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ], [ -1, 3, -2, -1, 2, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 7 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ], [ -1, 3, -1, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ -1, 3, -1, -1, 1, 0 ], [ -2, 4, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ -1, 3, -1, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ] ], 5.5 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ 0, 2, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 0, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ], [ 0, 2, -2, -1, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -3, -1, 1, 0 ], [ 0, 2, -2, -1, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ] ], 4 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -3, -1, 1, 0 ], [ 0, 3, -2, -2, 1, 0 ], [ -1, 2, -2, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -3, -1, 1, 0 ], [ 0, 3, -2, -2, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ 0, 3, -2, -2, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ] ], 5.625 ] - ], - [ - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ] ], 0 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ] ], 6.5 ], - [ [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ "Rest" ], [ -1, 3, -2, -1, 1, -1 ] ], 0 ], - [ [ [ "Rest" ], [ -2, 3, -2, 0, 1, 0 ], [ "Rest" ], [ -1, 3, -2, -1, 1, -1 ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ -1, 3, -2, -1, 1, -1 ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 6.375 ] - ] - ] -], -"last_changes": -[ - [ [ -2, 3, -2, -1, 1, 0 ], [ -1, 3, -3, -1, 1, 0 ], [ 0, 3, -2, -2, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ 0, 3, -2, -2, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 3, -2, -1, 1, 0 ], [ -2, 3, -1, -1, 1, 0 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, -1, 1, 1 ], [ -1, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ] ], - [ [ -2, 3, -2, -1, 1, 0 ], [ -2, 3, -2, 0, 1, 0 ], [ -1, 3, -2, -1, 1, 0 ], [ -1, 3, -2, -1, 1, -1 ] ] -], -"cur_uid": "tmp", -"ref_uid": 62300302, -"order_seed": 209649, -"dur_seed": 306774, -"motifs_seed": 821280, -"entrances_probs_vals": [ 1, 0, 2.9365079365079, 0.47, 2.8021978021978, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 2.7380952380952, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 2.7380952380952, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ -1200, 1200, 0, 0, 0.35390946502058, 0, 0.5, 0.5, 0.62139917695473, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8.0714285714286, 10.091836734694 ], -"passages_size": [ 0, 10 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3.json b/resources/resources_bak_2024_01_03/string_quartet_3.json deleted file mode 100644 index f4e9aa1..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3.json +++ /dev/null @@ -1,21 +0,0 @@ -{ -"ledger": -[ - "5201b8af", - "781442dc", - "6f0f638f", - "577cf188", - "7c2de94c", - "5488f7e9", - "5ec14635", - "726a40c7", - "55f9b81e", - "45fa07e8", - "6a9928d6", - "55bd25a1", - "75316bf0", - "69c568c6", - "4ff624b0", - "7e230015" -] -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3.json_bak b/resources/resources_bak_2024_01_03/string_quartet_3.json_bak deleted file mode 100644 index 4417271..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3.json_bak +++ /dev/null @@ -1,20 +0,0 @@ -{ -"ledger": -[ - "5201b8af", - "781442dc", - "6f0f638f", - "577cf188", - "7c2de94c", - "5488f7e9", - "5ec14635", - "726a40c7", - "55f9b81e", - "45fa07e8", - "6a9928d6", - "55bd25a1", - "75316bf0", - "69c568c6", - "4ff624b0" -] -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/45fa07e8/45fa07e8_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3/45fa07e8/45fa07e8_code.scd deleted file mode 100644 index 92aa171..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/45fa07e8/45fa07e8_code.scd +++ /dev/null @@ -1,966 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - if(pDistance < 0, {stepFunc.value(abs(pDistance))}, {0.001}); - //stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - - - if(rangeScore.value(candidate, [0, 0, 0, 0, 0, 0], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - }, { - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - }); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/45fa07e8/45fa07e8_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3/45fa07e8/45fa07e8_mus_model.json deleted file mode 100644 index 10b6bb0..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/45fa07e8/45fa07e8_mus_model.json +++ /dev/null @@ -1,443 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ 2, -5, 0, 3, -1, -1 ], [ "Rest" ], [ "Rest" ] ], 1.5 ], - [ [ [ "Rest" ], [ 2, -5, 0, 3, -1, -1 ], [ "Rest" ], [ 4, -5, -1, 2, -1, -1 ] ], 1.75 ], - [ [ [ 2, -5, -1, 3, -1, -1 ], [ 2, -5, 0, 3, -1, -1 ], [ "Rest" ], [ 4, -5, -1, 2, -1, -1 ] ], 1 ], - [ [ [ 2, -5, -1, 3, -1, -1 ], [ 2, -5, 0, 3, -1, -1 ], [ 4, -5, -1, 2, 0, -1 ], [ 4, -5, -1, 2, -1, -1 ] ], 1.375 ] - ], - [ - [ [ [ 2, -5, -1, 3, -1, -1 ], [ 4, -5, -1, 1, -1, -1 ], [ 4, -5, -1, 2, 0, -1 ], [ 4, -5, -1, 2, -1, -1 ] ], 0.875 ] - ], - [ - [ [ [ 2, -5, -1, 3, -1, -1 ], [ 4, -5, -1, 1, -1, -1 ], [ 4, -5, -1, 2, 0, -1 ], [ 3, -4, -1, 2, 0, -1 ] ], 1.625 ] - ], - [ - [ [ [ 2, -5, -1, 3, -1, -1 ], [ 3, -5, -1, 3, -1, -1 ], [ 4, -5, -1, 2, 0, -1 ], [ 3, -4, -1, 2, 0, -1 ] ], 0.75 ] - ], - [ - [ [ [ 2, -5, -1, 3, -1, -1 ], [ 4, -6, -1, 2, 0, -1 ], [ 4, -5, -1, 2, 0, -1 ], [ 3, -4, -1, 2, 0, -1 ] ], 1.75 ] - ], - [ - [ [ [ 3, -6, -1, 2, 0, -1 ], [ 4, -6, -1, 2, 0, -1 ], [ 4, -5, -1, 2, 0, -1 ], [ 3, -4, -1, 2, 0, -1 ] ], 1.375 ] - ], - [ - [ [ [ 3, -6, -1, 2, 0, -1 ], [ 4, -5, -1, 2, -1, -1 ], [ 4, -5, -1, 2, 0, -1 ], [ 3, -4, -1, 2, 0, -1 ] ], 1.125 ] - ], - [ - [ [ [ 3, -6, -1, 2, 0, -1 ], [ 4, -5, -1, 2, -1, -1 ], [ 3, -4, -1, 2, 1, -1 ], [ 3, -4, -1, 2, 0, -1 ] ], 1.625 ] - ], - [ - [ [ [ 3, -6, -1, 2, 0, -1 ], [ 4, -5, -1, 2, -1, -1 ], [ 3, -4, -1, 2, 1, -1 ], [ 2, -3, -1, 2, 1, -1 ] ], 1.125 ] - ], - [ - [ [ [ 3, -6, -1, 2, 0, -1 ], [ 4, -5, -1, 2, -1, -1 ], [ 3, -4, -1, 2, 1, -1 ], [ 3, -4, -2, 2, 1, -1 ] ], 1.5 ] - ], - [ - [ [ [ 3, -6, -1, 2, 0, -1 ], [ 4, -5, -1, 2, -1, -1 ], [ 4, -5, -2, 2, 1, -1 ], [ 3, -4, -2, 2, 1, -1 ] ], 1.375 ] - ], - [ - [ [ [ 3, -5, -2, 2, 0, -1 ], [ 4, -5, -1, 2, -1, -1 ], [ 4, -5, -2, 2, 1, -1 ], [ 3, -4, -2, 2, 1, -1 ] ], 1.5 ] - ], - [ - [ [ [ 3, -5, -2, 2, 0, -1 ], [ 4, -5, -2, 2, 0, -1 ], [ 4, -5, -2, 2, 1, -1 ], [ 3, -4, -2, 2, 1, -1 ] ], 1.625 ] - ], - [ - [ [ [ 3, -5, -2, 2, 0, -1 ], [ 4, -5, -2, 2, 0, -1 ], [ 4, -5, -2, 2, 1, -1 ], [ 5, -5, -2, 1, 0, -1 ] ], 1.25 ] - ], - [ - [ [ [ 3, -5, -2, 2, 0, -1 ], [ 4, -5, -3, 2, 1, -1 ], [ 4, -5, -2, 2, 1, -1 ], [ 5, -5, -2, 1, 0, -1 ] ], 1.75 ] - ], - [ - [ [ [ 3, -5, -2, 2, 0, -1 ], [ 4, -5, -3, 2, 1, -1 ], [ 4, -5, -2, 2, 1, -1 ], [ 3, -5, -2, 3, 1, -1 ] ], 0.875 ] - ], - [ - [ [ [ 3, -5, -2, 2, 0, -1 ], [ 5, -5, -2, 1, 0, -1 ], [ 4, -5, -2, 2, 1, -1 ], [ 3, -5, -2, 3, 1, -1 ] ], 0.625 ] - ], - [ - [ [ [ 3, -5, -2, 2, 0, -1 ], [ 5, -6, -2, 2, 0, -1 ], [ 4, -5, -2, 2, 1, -1 ], [ 3, -5, -2, 3, 1, -1 ] ], 0.75 ] - ], - [ - [ [ [ 3, -5, -2, 2, 0, -1 ], [ 5, -6, -2, 2, 0, -1 ], [ 4, -5, -2, 2, 1, -1 ], [ 5, -5, -2, 2, 0, -2 ] ], 1.125 ] - ], - [ - [ [ [ 3, -5, -2, 2, 0, -1 ], [ 6, -5, -2, 1, 0, -2 ], [ 4, -5, -2, 2, 1, -1 ], [ 5, -5, -2, 2, 0, -2 ] ], 1.5 ] - ], - [ - [ [ [ 4, -4, -2, 1, 0, -2 ], [ 6, -5, -2, 1, 0, -2 ], [ 4, -5, -2, 2, 1, -1 ], [ 5, -5, -2, 2, 0, -2 ] ], 1.375 ] - ], - [ - [ [ [ 4, -4, -2, 1, 0, -2 ], [ 6, -4, -2, 1, -1, -2 ], [ 4, -5, -2, 2, 1, -1 ], [ 5, -5, -2, 2, 0, -2 ] ], 1.625 ] - ], - [ - [ [ [ 4, -4, -2, 1, 0, -2 ], [ 6, -4, -2, 1, -1, -2 ], [ 6, -5, -2, 2, 0, -3 ], [ 5, -5, -2, 2, 0, -2 ] ], 1.375 ] - ], - [ - [ [ [ 5, -4, -2, 1, -2, -2 ], [ 6, -4, -2, 1, -1, -2 ], [ 6, -5, -2, 2, 0, -3 ], [ 5, -5, -2, 2, 0, -2 ] ], 0.75 ] - ], - [ - [ [ [ 5, -4, -2, 1, -2, -2 ], [ 6, -4, -2, 1, -1, -2 ], [ 5, -5, -1, 2, 0, -2 ], [ 5, -5, -2, 2, 0, -2 ] ], 1.375 ] - ], - [ - [ [ [ 5, -4, -2, 1, -2, -2 ], [ 6, -4, -2, 1, -1, -2 ], [ 5, -5, -2, 1, -1, -2 ], [ 5, -5, -2, 2, 0, -2 ] ], 1 ] - ], - [ - [ [ [ 5, -4, -2, 1, -2, -2 ], [ 6, -4, -2, 1, -1, -2 ], [ 4, -4, -2, 1, 0, -2 ], [ 5, -5, -2, 2, 0, -2 ] ], 1.625 ] - ], - [ - [ [ [ 5, -4, -2, 1, -2, -2 ], [ 6, -4, -2, 1, -1, -2 ], [ 4, -3, -2, 1, -1, -2 ], [ 5, -5, -2, 2, 0, -2 ] ], 1.625 ] - ], - [ - [ [ [ 5, -4, -2, 1, -2, -2 ], [ 5, -3, -2, 1, -2, -2 ], [ 4, -3, -2, 1, -1, -2 ], [ 5, -5, -2, 2, 0, -2 ] ], 1 ] - ], - [ - [ [ [ 4, -5, -2, 2, 0, -2 ], [ 5, -3, -2, 1, -2, -2 ], [ 4, -3, -2, 1, -1, -2 ], [ 5, -5, -2, 2, 0, -2 ] ], 1.125 ] - ], - [ - [ [ [ 4, -5, -2, 2, 0, -2 ], [ 5, -3, -2, 1, -2, -2 ], [ 5, -3, -2, 1, -3, -2 ], [ 5, -5, -2, 2, 0, -2 ] ], 0.75 ] - ], - [ - [ [ [ 4, -5, -2, 2, 0, -2 ], [ 5, -5, -2, 2, -1, -2 ], [ 5, -3, -2, 1, -3, -2 ], [ 5, -5, -2, 2, 0, -2 ] ], 1.5 ] - ], - [ - [ [ [ 4, -5, -2, 1, -1, -2 ], [ 5, -5, -2, 2, -1, -2 ], [ 5, -3, -2, 1, -3, -2 ], [ 5, -5, -2, 2, 0, -2 ] ], 0.875 ] - ], - [ - [ [ [ 4, -5, -2, 1, -1, -2 ], [ 4, -4, -2, 2, 0, -2 ], [ 5, -3, -2, 1, -3, -2 ], [ 5, -5, -2, 2, 0, -2 ] ], 1.75 ] - ], - [ - [ [ [ 4, -5, -2, 1, -1, -2 ], [ 4, -4, -2, 2, 0, -2 ], [ 5, -5, -2, 1, 0, -2 ], [ 5, -5, -2, 2, 0, -2 ] ], 0.875 ] - ], - [ - [ [ [ 4, -5, -2, 1, -1, -2 ], [ 4, -4, -2, 2, 0, -2 ], [ 5, -4, -2, 1, -1, -2 ], [ 5, -5, -2, 2, 0, -2 ] ], 0.875 ] - ], - [ - [ [ [ 4, -5, -2, 1, -1, -2 ], [ 4, -4, -2, 2, 0, -2 ], [ 4, -5, -1, 2, 0, -2 ], [ 5, -5, -2, 2, 0, -2 ] ], 1.5 ] - ], - [ - [ [ [ 4, -5, -2, 1, -1, -2 ], [ 4, -4, -2, 2, 0, -2 ], [ 5, -6, -2, 2, 0, -2 ], [ 5, -5, -2, 2, 0, -2 ] ], 0.875 ] - ], - [ - [ [ [ 4, -5, -2, 1, -1, -2 ], [ 4, -5, -2, 2, 0, -1 ], [ 5, -6, -2, 2, 0, -2 ], [ 5, -5, -2, 2, 0, -2 ] ], 1.625 ] - ], - [ - [ [ [ 4, -5, -2, 1, -1, -2 ], [ 4, -5, -2, 2, 0, -1 ], [ 5, -5, -2, 2, -1, -2 ], [ 5, -5, -2, 2, 0, -2 ] ], 1.125 ] - ], - [ - [ [ [ 4, -5, -2, 1, -1, -2 ], [ 4, -5, -2, 2, 0, -1 ], [ 5, -5, -2, 2, -1, -2 ], [ 5, -4, -2, 2, -1, -2 ] ], 1.5 ] - ], - [ - [ [ [ 4, -5, -2, 1, -1, -2 ], [ 5, -4, -3, 2, -1, -2 ], [ 5, -5, -2, 2, -1, -2 ], [ 5, -4, -2, 2, -1, -2 ] ], 0.875 ] - ], - [ - [ [ [ 4, -5, -2, 1, -1, -2 ], [ 5, -4, -3, 2, -1, -2 ], [ 5, -5, -2, 2, -1, -2 ], [ 6, -5, -3, 2, -1, -2 ] ], 1.5 ] - ], - [ - [ [ [ 4, -5, -2, 1, -1, -2 ], [ 5, -4, -3, 2, -1, -2 ], [ 6, -6, -3, 2, -1, -2 ], [ 6, -5, -3, 2, -1, -2 ] ], 1.25 ] - ], - [ - [ [ [ 4, -5, -2, 1, -1, -2 ], [ 5, -4, -3, 2, -1, -2 ], [ 6, -5, -2, 1, -1, -2 ], [ 6, -5, -3, 2, -1, -2 ] ], 1.5 ] - ], - [ - [ [ [ 4, -5, -2, 1, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ], [ 6, -5, -2, 1, -1, -2 ], [ 6, -5, -3, 2, -1, -2 ] ], 0.75 ] - ], - [ - [ [ [ 4, -5, -2, 1, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ], [ 6, -5, -2, 1, -1, -2 ], [ 6, -4, -2, 1, -1, -2 ] ], 0.75 ] - ], - [ - [ [ [ 5, -5, -2, 0, -1, -2 ], [ 7, -5, -2, 0, -1, -2 ], [ 6, -5, -2, 1, -1, -2 ], [ 6, -4, -2, 1, -1, -2 ] ], 1.125 ] - ], - [ - [ [ [ 5, -5, -2, 1, -1, -3 ], [ 7, -5, -2, 0, -1, -2 ], [ 6, -5, -2, 1, -1, -2 ], [ 6, -4, -2, 1, -1, -2 ] ], 1.625 ] - ], - [ - [ [ [ 5, -5, -2, 1, -1, -3 ], [ 6, -4, -3, 1, -1, -2 ], [ 6, -5, -2, 1, -1, -2 ], [ 6, -4, -2, 1, -1, -2 ] ], 1.75 ] - ], - [ - [ [ [ 5, -5, -2, 1, -1, -3 ], [ 6, -4, -3, 1, -1, -2 ], [ 5, -3, -2, 1, -1, -2 ], [ 6, -4, -2, 1, -1, -2 ] ], 0.875 ] - ], - [ - [ [ [ 4, -4, -2, 1, -1, -2 ], [ 6, -4, -3, 1, -1, -2 ], [ 5, -3, -2, 1, -1, -2 ], [ 6, -4, -2, 1, -1, -2 ] ], 1.25 ] - ], - [ - [ [ [ 4, -4, -2, 1, -1, -2 ], [ 6, -4, -3, 1, -1, -2 ], [ 5, -4, -2, 1, -1, -2 ], [ 6, -4, -2, 1, -1, -2 ] ], 1.625 ] - ], - [ - [ [ [ 4, -4, -2, 1, -1, -2 ], [ 5, -4, -2, 2, -1, -2 ], [ 5, -4, -2, 1, -1, -2 ], [ 6, -4, -2, 1, -1, -2 ] ], 1.875 ] - ], - [ - [ [ [ 4, -4, -2, 1, -1, -2 ], [ 3, -3, -2, 1, -1, -2 ], [ 5, -4, -2, 1, -1, -2 ], [ 6, -4, -2, 1, -1, -2 ] ], 1.625 ] - ], - [ - [ [ [ 4, -4, -2, 1, -1, -2 ], [ 4, -4, -3, 1, -1, -2 ], [ 5, -4, -2, 1, -1, -2 ], [ 6, -4, -2, 1, -1, -2 ] ], 1.5 ] - ], - [ - [ [ [ 4, -4, -2, 1, -1, -2 ], [ 4, -4, -3, 1, -1, -2 ], [ 5, -4, -2, 1, -1, -2 ], [ 5, -4, -3, 1, -1, -2 ] ], 0.625 ] - ], - [ - [ [ [ 4, -4, -2, 1, -1, -2 ], [ 3, -4, -2, 2, -1, -2 ], [ 5, -4, -2, 1, -1, -2 ], [ 5, -4, -3, 1, -1, -2 ] ], 1.625 ] - ], - [ - [ [ [ 4, -4, -2, 1, -1, -2 ], [ 5, -4, -3, 0, -1, -2 ], [ 5, -4, -2, 1, -1, -2 ], [ 5, -4, -3, 1, -1, -2 ] ], 1.625 ] - ], - [ - [ [ [ 5, -4, -3, 1, -2, -2 ], [ 5, -4, -3, 0, -1, -2 ], [ 5, -4, -2, 1, -1, -2 ], [ 5, -4, -3, 1, -1, -2 ] ], 0.875 ] - ], - [ - [ [ [ 5, -4, -3, 1, -2, -2 ], [ 5, -4, -3, 0, -1, -2 ], [ 6, -5, -3, 1, -1, -2 ], [ 5, -4, -3, 1, -1, -2 ] ], 1.125 ] - ], - [ - [ [ [ 4, -3, -3, 1, -1, -2 ], [ 5, -4, -3, 0, -1, -2 ], [ 6, -5, -3, 1, -1, -2 ], [ 5, -4, -3, 1, -1, -2 ] ], 1 ] - ], - [ - [ [ [ 4, -3, -3, 1, -1, -2 ], [ 5, -4, -3, 0, -1, -2 ], [ 6, -5, -3, 1, -1, -2 ], [ 6, -5, -4, 1, -1, -2 ] ], 1.5 ] - ], - [ - [ [ [ 5, -5, -2, 1, -1, -2 ], [ 5, -4, -3, 0, -1, -2 ], [ 6, -5, -3, 1, -1, -2 ], [ 6, -5, -4, 1, -1, -2 ] ], 1 ] - ], - [ - [ [ [ 5, -5, -2, 1, -1, -2 ], [ 5, -4, -3, 0, -1, -2 ], [ 6, -5, -3, 1, -1, -2 ], [ 5, -5, -3, 1, -1, -1 ] ], 1.25 ] - ], - [ - [ [ [ 5, -5, -2, 1, -1, -2 ], [ 5, -4, -3, 0, -1, -2 ], [ 5, -5, -2, 1, -1, -1 ], [ 5, -5, -3, 1, -1, -1 ] ], 1.375 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 5, -4, -3, 0, -1, -2 ], [ 5, -5, -2, 1, -1, -1 ], [ 5, -5, -3, 1, -1, -1 ] ], 1.375 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 5, -4, -3, 0, -1, -2 ], [ 5, -5, -2, 1, -1, -1 ], [ 4, -5, -2, 2, -1, -1 ] ], 1.5 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 5, -4, -3, 0, -1, -2 ], [ 5, -5, -2, 1, -1, -1 ], [ 6, -7, -2, 1, -1, -1 ] ], 1.375 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 5, -4, -3, 0, -1, -2 ], [ 5, -5, -2, 1, -1, -1 ], [ 6, -6, -2, 1, -2, -1 ] ], 1.625 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 5, -4, -3, 0, -1, -2 ], [ 6, -6, -3, 1, -1, -1 ], [ 6, -6, -2, 1, -2, -1 ] ], 1.125 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 5, -4, -3, 0, -1, -2 ], [ 5, -6, -2, 2, -1, -1 ], [ 6, -6, -2, 1, -2, -1 ] ], 1.125 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 5, -4, -3, 0, -1, -2 ], [ 5, -6, -2, 2, -1, -1 ], [ 6, -4, -2, 0, -1, -2 ] ], 0.625 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 5, -4, -3, 0, -1, -2 ], [ 7, -4, -2, -1, -1, -2 ], [ 6, -4, -2, 0, -1, -2 ] ], 1 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 5, -7, -2, 1, -1, -1 ], [ 7, -4, -2, -1, -1, -2 ], [ 6, -4, -2, 0, -1, -2 ] ], 1.5 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 4, -4, -2, 1, -1, -2 ], [ 7, -4, -2, -1, -1, -2 ], [ 6, -4, -2, 0, -1, -2 ] ], 1.25 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 4, -5, -2, 1, -1, -1 ], [ 7, -4, -2, -1, -1, -2 ], [ 6, -4, -2, 0, -1, -2 ] ], 1.625 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 4, -5, -2, 1, -1, -1 ], [ 7, -4, -2, -1, -1, -2 ], [ 5, -6, -2, 1, -1, 0 ] ], 1 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 4, -5, -2, 1, -1, -1 ], [ 6, -6, -2, 1, -1, -1 ], [ 5, -6, -2, 1, -1, 0 ] ], 1.625 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 4, -5, -2, 1, -1, -1 ], [ 5, -6, -1, 1, -1, 0 ], [ 5, -6, -2, 1, -1, 0 ] ], 1.25 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 4, -5, -2, 1, -1, -1 ], [ 5, -6, -1, 1, -1, 0 ], [ 5, -6, -2, 2, -1, -1 ] ], 1 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 4, -5, -2, 1, -1, -1 ], [ 5, -6, -1, 1, -1, 0 ], [ 5, -5, -1, 1, -1, -1 ] ], 1.625 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 4, -6, -1, 1, -1, -1 ], [ 5, -6, -1, 1, -1, 0 ], [ 5, -5, -1, 1, -1, -1 ] ], 1.25 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 5, -7, -2, 1, -1, -1 ], [ 5, -6, -1, 1, -1, 0 ], [ 5, -5, -1, 1, -1, -1 ] ], 0.875 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 5, -7, -2, 1, -1, -1 ], [ 6, -5, -1, 0, -1, -1 ], [ 5, -5, -1, 1, -1, -1 ] ], 1.25 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 5, -7, -2, 1, -1, -1 ], [ 6, -5, -1, 0, -1, -1 ], [ 6, -6, -2, 1, -1, -1 ] ], 0.75 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 5, -7, -2, 1, -1, -1 ], [ 7, -7, -2, 1, -1, -1 ], [ 6, -6, -2, 1, -1, -1 ] ], 1.125 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 5, -7, -2, 1, -1, -1 ], [ 4, -6, -2, 1, -1, -1 ], [ 6, -6, -2, 1, -1, -1 ] ], 1.625 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 5, -7, -2, 1, -1, -1 ], [ 4, -6, -2, 1, -1, -1 ], [ 7, -7, -3, 1, -1, -1 ] ], 1.125 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 5, -7, -2, 1, -1, -1 ], [ 4, -6, -2, 1, -1, -1 ], [ 6, -7, -2, 1, -1, 0 ] ], 1.375 ] - ], - [ - [ [ [ 5, -6, -2, 1, -1, -1 ], [ 5, -7, -2, 1, -1, -1 ], [ 4, -6, -2, 1, -1, -1 ], [ 6, -6, -1, 1, -1, -1 ] ], 1.75 ] - ], - [ - [ [ [ 4, -6, -1, 1, -1, 0 ], [ 5, -7, -2, 1, -1, -1 ], [ 4, -6, -2, 1, -1, -1 ], [ 6, -6, -1, 1, -1, -1 ] ], 1.125 ] - ], - [ - [ [ [ 4, -6, -1, 1, -1, 0 ], [ 5, -7, -2, 1, -1, -1 ], [ 4, -6, -2, 1, -1, -1 ], [ 7, -7, -2, 1, -1, -1 ] ], 1.25 ] - ], - [ - [ [ [ 4, -6, -1, 1, -1, 0 ], [ 5, -7, -2, 1, -1, -1 ], [ 4, -7, -2, 1, -1, 0 ], [ 7, -7, -2, 1, -1, -1 ] ], 0.75 ] - ], - [ - [ [ [ 4, -6, -1, 1, -1, 0 ], [ 5, -7, -2, 1, -1, -1 ], [ 4, -7, -2, 1, -1, 0 ], [ 6, -7, -1, 1, -1, 0 ] ], 1 ] - ], - [ - [ [ [ 4, -6, -1, 1, -1, 0 ], [ 5, -7, -2, 1, -1, -1 ], [ 4, -7, -2, 1, -1, 0 ], [ 5, -6, -1, 1, 0, 0 ] ], 1.125 ] - ], - [ - [ [ [ 4, -6, -1, 1, -1, 0 ], [ 4, -7, -1, 1, -1, 0 ], [ 4, -7, -2, 1, -1, 0 ], [ 5, -6, -1, 1, 0, 0 ] ], 0.625 ] - ], - [ - [ [ [ 4, -6, -1, 1, -1, 0 ], [ 4, -7, -1, 1, -1, 0 ], [ 3, -5, -1, 1, 0, 0 ], [ 5, -6, -1, 1, 0, 0 ] ], 1.25 ] - ], - [ - [ [ [ 4, -6, -1, 1, -1, 0 ], [ 4, -7, -1, 1, -1, 0 ], [ 3, -5, -1, 1, 0, 0 ], [ 5, -6, -2, 1, -1, 0 ] ], 1.25 ] - ], - [ - [ [ [ 4, -6, -1, 1, -1, 0 ], [ 4, -7, -1, 1, -1, 0 ], [ 3, -5, -1, 1, 0, 0 ], [ 6, -7, -1, 1, -1, -1 ] ], 1 ], - [ [ [ 4, -6, -1, 1, -1, 0 ], [ "Rest" ], [ 3, -5, -1, 1, 0, 0 ], [ 6, -7, -1, 1, -1, -1 ] ], 1.375 ], - [ [ [ 4, -6, -1, 1, -1, 0 ], [ "Rest" ], [ 3, -5, -1, 1, 0, 0 ], [ "Rest" ] ], 1.125 ], - [ [ [ "Rest" ], [ "Rest" ], [ 3, -5, -1, 1, 0, 0 ], [ "Rest" ] ], 1.5 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 6.375 ] - ] - ] -], -"last_changes": -[ - [ [ 4, -6, -1, 1, -1, 0 ], [ 5, -7, -2, 1, -1, -1 ], [ 4, -7, -2, 1, -1, 0 ], [ 5, -6, -1, 1, 0, 0 ] ], - [ [ 4, -6, -1, 1, -1, 0 ], [ 4, -7, -1, 1, -1, 0 ], [ 4, -7, -2, 1, -1, 0 ], [ 5, -6, -1, 1, 0, 0 ] ], - [ [ 4, -6, -1, 1, -1, 0 ], [ 4, -7, -1, 1, -1, 0 ], [ 3, -5, -1, 1, 0, 0 ], [ 5, -6, -1, 1, 0, 0 ] ], - [ [ 4, -6, -1, 1, -1, 0 ], [ 4, -7, -1, 1, -1, 0 ], [ 3, -5, -1, 1, 0, 0 ], [ 5, -6, -2, 1, -1, 0 ] ], - [ [ 4, -6, -1, 1, -1, 0 ], [ 4, -7, -1, 1, -1, 0 ], [ 3, -5, -1, 1, 0, 0 ], [ 6, -7, -1, 1, -1, -1 ] ] -], -"cur_uid": "45fa07e8", -"ref_uid": "55f9b81e", -"order_seed": 921383, -"dur_seed": 545846, -"motifs_seed": 212473, -"entrances_probs_vals": [ 0, 0, 0, 0.66, 1.8406593406593, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 0.66, 1.8406593406593, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 0.66, 1.8406593406593, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2467, 2400 ], [ -1167, 2400 ], [ -702, 2400 ], [ -702, 2400 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.090534979423868, 0.92613636363636, 0.17489711934156, 0.079545454545455, 0.37037037037037, 0, 0.7201646090535, 0, 1, 0 ], -"passages_weights": [ 0.63, 0.62, 1, 0.41, 1 ], -"hd_exp": 6, -"hd_invert": 0, -"order": -[ - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 1, 3, 2 ], [ 0 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 2, 0, 3 ], [ 1 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 1, 3, 2 ], [ 0 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 1, 3, 2 ], [ 0 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ] -], -"sus_weights": [ 0, 0, 0.61 ], -"order_size": [ 100, 100 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/4ff624b0/4ff624b0_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3/4ff624b0/4ff624b0_code.scd deleted file mode 100644 index 0d8c24b..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/4ff624b0/4ff624b0_code.scd +++ /dev/null @@ -1,975 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/4ff624b0/4ff624b0_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3/4ff624b0/4ff624b0_mus_model.json deleted file mode 100644 index 0ef2a04..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/4ff624b0/4ff624b0_mus_model.json +++ /dev/null @@ -1,552 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 1, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, -1, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 1, -1, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, -1, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 1, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 1, 0, -1, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, 0, -1, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, 0, -1, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 1, 0, -1, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 0, 1, 0, -1, 0 ] ], 1 ] - ], - [ - [ [ [ 1, 0, -1, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, -1, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, -1, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 1, -1, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 1 ], - [ [ [ 1, -1, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 1, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 1, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 1, 0, 0, 0, 0 ], [ -2, 2, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 2, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 2, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -2, 2, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 1, 0, 0 ] ], 1 ], - [ [ [ -1, 2, 0, 0, 0, 0 ], [ -2, 2, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 1, 0, 0 ] ], 1 ], - [ [ [ -1, 2, 0, 0, 0, 0 ], [ -1, 1, -1, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 2, 0, 0, 0, 0 ], [ -1, 1, -1, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ -1, 1, 0, 1, 0, 0 ] ], 1 ], - [ [ [ 0, 1, -1, 0, 0, 0 ], [ -1, 1, -1, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ -1, 1, 0, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 1, -1, 0, 0, 0 ], [ 0, 1, -1, -1, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ -1, 1, 0, 1, 0, 0 ] ], 1 ], - [ [ [ 0, 1, -1, 0, 0, 0 ], [ 0, 1, -1, -1, 0, 0 ], [ -1, 2, -1, 0, 0, 0 ], [ -1, 1, 0, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 3, -1, 0, 0, 0 ], [ 0, 1, -1, -1, 0, 0 ], [ -1, 2, -1, 0, 0, 0 ], [ -1, 1, 0, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 3, -1, 0, 0, 0 ], [ 0, 1, -1, -1, 0, 0 ], [ -1, 2, -1, 0, 0, 0 ], [ -2, 3, -1, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 3, -1, 0, 0, 0 ], [ 0, 1, -1, -1, 0, 0 ], [ -1, 3, -1, 0, -1, 0 ], [ -2, 3, -1, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 3, -1, 0, 0, 0 ], [ -1, 3, -1, -1, 0, 0 ], [ -1, 3, -1, 0, -1, 0 ], [ -2, 3, -1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 3, -1, 0, 0, 0 ], [ -1, 3, -1, -1, 0, 0 ], [ -1, 3, -1, 0, -1, 0 ], [ -2, 4, -1, 0, -1, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 3, -1, 0, 0, 0 ], [ -1, 3, -1, -1, 0, 0 ], [ -1, 3, -1, 0, -1, 0 ], [ 0, 3, 0, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 3, -1, -1, 0, 0 ], [ -1, 3, -1, -1, 0, 0 ], [ -1, 3, -1, 0, -1, 0 ], [ 0, 3, 0, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 3, -1, -1, 0, 0 ], [ -1, 3, -1, -1, 0, 0 ], [ 0, 2, -1, -1, 0, 0 ], [ 0, 3, 0, -1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 3, -1, -1, 0, 0 ], [ -1, 3, -1, -1, 0, 0 ], [ -1, 4, -1, -1, 0, 0 ], [ 0, 3, 0, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 3, -1, -1, 0, 0 ], [ -1, 3, -1, -1, 0, 0 ], [ -1, 4, -1, -1, 0, 0 ], [ 0, 2, -1, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 3, -1, -1, 0, 0 ], [ -1, 2, -1, -1, 0, 0 ], [ -1, 4, -1, -1, 0, 0 ], [ 0, 2, -1, -1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 3, -1, -1, 0, 0 ], [ -2, 4, -1, -1, 0, 0 ], [ -1, 4, -1, -1, 0, 0 ], [ 0, 2, -1, -1, 0, 0 ] ], 1 ], - [ [ [ -2, 5, -1, -1, 0, 0 ], [ -2, 4, -1, -1, 0, 0 ], [ -1, 4, -1, -1, 0, 0 ], [ 0, 2, -1, -1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 5, -1, -1, 0, 0 ], [ -2, 4, -1, -1, 0, 0 ], [ -1, 4, -1, -1, 0, 0 ], [ -1, 3, -1, -1, 0, 0 ] ], 1 ], - [ [ [ -2, 5, -1, -1, 0, 0 ], [ -3, 6, -1, -1, 0, 0 ], [ -1, 4, -1, -1, 0, 0 ], [ -1, 3, -1, -1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 5, -1, -1, 0, 0 ], [ -3, 6, -1, -1, 0, 0 ], [ -1, 4, -1, -1, 0, 0 ], [ -3, 7, -1, -1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 5, -1, -1, 0, 0 ], [ -3, 6, -1, -1, 0, 0 ], [ -2, 6, -1, -1, 0, 0 ], [ -3, 7, -1, -1, 0, 0 ] ], 1 ], - [ [ [ -2, 5, -1, -1, 0, 0 ], [ -4, 8, -1, -1, 0, 0 ], [ -2, 6, -1, -1, 0, 0 ], [ -3, 7, -1, -1, 0, 0 ] ], 1 ], - [ [ [ -3, 6, -1, -1, 0, 0 ], [ -4, 8, -1, -1, 0, 0 ], [ -2, 6, -1, -1, 0, 0 ], [ -3, 7, -1, -1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 7, -1, -1, 0, 0 ], [ -4, 8, -1, -1, 0, 0 ], [ -2, 6, -1, -1, 0, 0 ], [ -3, 7, -1, -1, 0, 0 ] ], 1 ], - [ [ [ -4, 7, -1, -1, 0, 0 ], [ -2, 7, -1, -1, 0, 0 ], [ -2, 6, -1, -1, 0, 0 ], [ -3, 7, -1, -1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 6, -1, -1, 0, 0 ], [ -2, 7, -1, -1, 0, 0 ], [ -2, 6, -1, -1, 0, 0 ], [ -3, 7, -1, -1, 0, 0 ] ], 1 ], - [ [ [ -4, 6, -1, -1, 0, 0 ], [ -2, 7, -1, -1, 0, 0 ], [ -3, 8, -1, -1, 0, 0 ], [ -3, 7, -1, -1, 0, 0 ] ], 1 ], - [ [ [ -4, 6, -1, -1, 0, 0 ], [ -2, 6, -1, -1, 0, 0 ], [ -3, 8, -1, -1, 0, 0 ], [ -3, 7, -1, -1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 6, -1, -1, 0, 0 ], [ -2, 6, -1, -1, 0, 0 ], [ -3, 8, -1, -1, 0, 0 ], [ -3, 7, -1, -1, 0, 0 ] ], 1 ], - [ [ [ -3, 6, -1, -1, 0, 0 ], [ -2, 6, -1, -1, 0, 0 ], [ -3, 7, -1, -1, 0, 1 ], [ -3, 7, -1, -1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 6, -1, -1, 0, 0 ], [ -2, 6, -1, -1, 0, 0 ], [ -3, 7, -1, -1, 0, 1 ], [ -3, 6, -1, -1, 0, 1 ] ], 1 ], - [ [ [ -3, 6, -1, -1, 0, 0 ], [ -4, 7, -1, 0, 0, 1 ], [ -3, 7, -1, -1, 0, 1 ], [ -3, 6, -1, -1, 0, 1 ] ], 1 ], - [ [ [ -5, 7, -1, 0, 0, 1 ], [ -4, 7, -1, 0, 0, 1 ], [ -3, 7, -1, -1, 0, 1 ], [ -3, 6, -1, -1, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -4, 7, -1, -1, 0, 1 ], [ -4, 7, -1, 0, 0, 1 ], [ -3, 7, -1, -1, 0, 1 ], [ -3, 6, -1, -1, 0, 1 ] ], 1 ], - [ [ [ -4, 7, -1, -1, 0, 1 ], [ -4, 7, -1, 0, 0, 1 ], [ -4, 7, 0, 0, 0, 1 ], [ -3, 6, -1, -1, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -4, 7, -1, -1, 0, 1 ], [ -4, 7, -1, 0, 0, 1 ], [ -3, 6, -1, 0, 0, 1 ], [ -3, 6, -1, -1, 0, 1 ] ], 1 ], - [ [ [ -4, 7, -1, -1, 0, 1 ], [ -3, 7, -1, -1, 0, 1 ], [ -3, 6, -1, 0, 0, 1 ], [ -3, 6, -1, -1, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -3, 5, -1, -1, 0, 1 ], [ -3, 7, -1, -1, 0, 1 ], [ -3, 6, -1, 0, 0, 1 ], [ -3, 6, -1, -1, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -3, 5, -1, -1, 0, 1 ], [ -3, 7, -1, -1, 0, 1 ], [ -3, 6, -1, 0, 0, 1 ], [ -3, 5, -1, 0, 0, 1 ] ], 1 ], - [ [ [ -3, 5, -1, -1, 0, 1 ], [ -2, 5, -1, -1, 0, 1 ], [ -3, 6, -1, 0, 0, 1 ], [ -3, 5, -1, 0, 0, 1 ] ], 1 ], - [ [ [ -3, 5, -1, -1, 0, 1 ], [ -2, 5, -1, -1, 0, 1 ], [ -2, 5, 0, -1, 0, 1 ], [ -3, 5, -1, 0, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -3, 5, -1, -1, 0, 1 ], [ -1, 5, -1, -2, 0, 1 ], [ -2, 5, 0, -1, 0, 1 ], [ -3, 5, -1, 0, 0, 1 ] ], 1 ], - [ [ [ -3, 5, -1, -1, 0, 1 ], [ -1, 5, -1, -2, 0, 1 ], [ -1, 4, -1, -1, 0, 1 ], [ -3, 5, -1, 0, 0, 1 ] ], 1 ], - [ [ [ -3, 5, -1, -1, 0, 1 ], [ -1, 5, -1, -2, 0, 1 ], [ -1, 4, -1, -1, 0, 1 ], [ -2, 5, -1, -1, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -2, 5, -1, -2, 0, 1 ], [ -1, 5, -1, -2, 0, 1 ], [ -1, 4, -1, -1, 0, 1 ], [ -2, 5, -1, -1, 0, 1 ] ], 1 ], - [ [ [ -2, 5, -1, -2, 0, 1 ], [ -1, 5, -1, -2, 0, 1 ], [ -1, 4, -1, -2, 0, 1 ], [ -2, 5, -1, -1, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -2, 5, -1, -2, 0, 1 ], [ -1, 5, -1, -2, 0, 1 ], [ -2, 6, -1, -2, 0, 1 ], [ -2, 5, -1, -1, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -2, 5, -1, -2, 0, 1 ], [ -1, 5, -1, -2, 0, 1 ], [ -1, 5, -2, -2, 0, 1 ], [ -2, 5, -1, -1, 0, 1 ] ], 1 ], - [ [ [ -2, 4, -1, -2, 0, 1 ], [ -1, 5, -1, -2, 0, 1 ], [ -1, 5, -2, -2, 0, 1 ], [ -2, 5, -1, -1, 0, 1 ] ], 1 ], - [ [ [ -2, 4, -1, -2, 0, 1 ], [ -1, 5, -1, -2, 0, 1 ], [ -1, 5, -2, -2, 0, 1 ], [ -1, 4, -1, -2, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -3, 6, -1, -2, 0, 1 ], [ -1, 5, -1, -2, 0, 1 ], [ -1, 5, -2, -2, 0, 1 ], [ -1, 4, -1, -2, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -3, 6, -1, -2, 0, 1 ], [ -1, 5, -1, -2, 0, 1 ], [ -1, 5, -2, -2, 0, 1 ], [ -2, 6, -1, -2, 0, 1 ] ], 1 ], - [ [ [ -3, 6, -1, -2, 0, 1 ], [ -1, 5, -1, -2, 0, 1 ], [ -2, 5, -1, -2, 0, 1 ], [ -2, 6, -1, -2, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -3, 6, -1, -2, 0, 1 ], [ -1, 5, -1, -2, 0, 1 ], [ -2, 5, -1, -2, 0, 1 ], [ -1, 5, -2, -2, 0, 1 ] ], 1 ], - [ [ [ -3, 6, -1, -2, 0, 1 ], [ -1, 5, -1, -2, 0, 1 ], [ -1, 5, -1, -3, 0, 1 ], [ -1, 5, -2, -2, 0, 1 ] ], 1 ], - [ [ [ -2, 5, -2, -2, 0, 1 ], [ -1, 5, -1, -2, 0, 1 ], [ -1, 5, -1, -3, 0, 1 ], [ -1, 5, -2, -2, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -2, 5, -2, -3, 0, 1 ], [ -1, 5, -1, -2, 0, 1 ], [ -1, 5, -1, -3, 0, 1 ], [ -1, 5, -2, -2, 0, 1 ] ], 1 ], - [ [ [ -2, 5, -2, -3, 0, 1 ], [ 0, 5, -1, -3, 0, 1 ], [ -1, 5, -1, -3, 0, 1 ], [ -1, 5, -2, -2, 0, 1 ] ], 1 ], - [ [ [ -2, 5, -2, -3, 0, 1 ], [ 0, 5, -1, -3, 0, 1 ], [ -1, 5, -1, -3, 0, 1 ], [ -1, 6, -1, -3, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -2, 5, -2, -3, 0, 1 ], [ 0, 5, -1, -3, 0, 1 ], [ -1, 5, -1, -3, 0, 1 ], [ -1, 5, -2, -3, 0, 1 ] ], 1 ], - [ [ [ -2, 5, -2, -3, 0, 1 ], [ 1, 4, -2, -3, 0, 1 ], [ -1, 5, -1, -3, 0, 1 ], [ -1, 5, -2, -3, 0, 1 ] ], 1 ], - [ [ [ -2, 5, -2, -3, 0, 1 ], [ 1, 4, -2, -3, 0, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ -1, 5, -2, -3, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -2, 5, -2, -3, 0, 1 ], [ 0, 5, -2, -3, 0, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ -1, 5, -2, -3, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -2, 5, -2, -3, 0, 1 ], [ 1, 5, -2, -4, 0, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ -1, 5, -2, -3, 0, 1 ] ], 1 ], - [ [ [ -1, 5, -2, -4, 0, 1 ], [ 1, 5, -2, -4, 0, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ -1, 5, -2, -3, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -1, 5, -2, -4, 0, 1 ], [ 1, 5, -2, -4, 0, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ 0, 5, -2, -4, 0, 1 ] ], 1 ], - [ [ [ -1, 5, -2, -4, 0, 1 ], [ 0, 6, -2, -4, 0, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ 0, 5, -2, -4, 0, 1 ] ], 1 ], - [ [ [ -1, 5, -2, -4, 0, 1 ], [ 0, 6, -2, -4, 0, 1 ], [ 0, 5, -1, -4, 0, 1 ], [ 0, 5, -2, -4, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -2, 5, -1, -4, 0, 1 ], [ 0, 6, -2, -4, 0, 1 ], [ 0, 5, -1, -4, 0, 1 ], [ 0, 5, -2, -4, 0, 1 ] ], 1 ], - [ [ [ -2, 5, -1, -4, 0, 1 ], [ 0, 5, -1, -4, 1, 1 ], [ 0, 5, -1, -4, 0, 1 ], [ 0, 5, -2, -4, 0, 1 ] ], 1 ], - [ [ [ -2, 5, -1, -4, 0, 1 ], [ 0, 5, -1, -4, 1, 1 ], [ 0, 5, -1, -4, 0, 1 ], [ -1, 5, -1, -4, 1, 1 ] ], 1 ] - ], - [ - [ [ [ -2, 5, -1, -4, 0, 1 ], [ -1, 6, -1, -4, 0, 1 ], [ 0, 5, -1, -4, 0, 1 ], [ -1, 5, -1, -4, 1, 1 ] ], 1 ], - [ [ [ -1, 5, -1, -5, 0, 1 ], [ -1, 6, -1, -4, 0, 1 ], [ 0, 5, -1, -4, 0, 1 ], [ -1, 5, -1, -4, 1, 1 ] ], 1 ] - ], - [ - [ [ [ -1, 5, -1, -5, 0, 1 ], [ -1, 6, -1, -4, 0, 1 ], [ 0, 5, -1, -4, 0, 1 ], [ 1, 4, -1, -5, 0, 1 ] ], 1 ], - [ [ [ -1, 5, -1, -5, 0, 1 ], [ 0, 6, -1, -5, 0, 1 ], [ 0, 5, -1, -4, 0, 1 ], [ 1, 4, -1, -5, 0, 1 ] ], 1 ], - [ [ [ -1, 5, -1, -5, 0, 1 ], [ 0, 6, -1, -5, 0, 1 ], [ 1, 5, -1, -5, 0, 1 ], [ 1, 4, -1, -5, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -1, 5, -1, -5, 0, 1 ], [ 0, 5, -1, -5, 0, 1 ], [ 1, 5, -1, -5, 0, 1 ], [ 1, 4, -1, -5, 0, 1 ] ], 1 ], - [ [ [ 0, 4, -1, -5, 0, 1 ], [ 0, 5, -1, -5, 0, 1 ], [ 1, 5, -1, -5, 0, 1 ], [ 1, 4, -1, -5, 0, 1 ] ], 1 ], - [ [ [ 0, 4, -1, -5, 0, 1 ], [ 0, 5, -1, -5, 0, 1 ], [ 2, 4, -1, -5, 0, 1 ], [ 1, 4, -1, -5, 0, 1 ] ], 1 ] - ], - [ - [ [ [ 0, 4, -1, -5, 0, 1 ], [ 0, 5, -1, -5, 0, 1 ], [ 2, 4, -1, -5, 0, 1 ], [ 0, 6, -1, -5, 0, 1 ] ], 1 ], - [ [ [ 0, 4, -1, -5, 0, 1 ], [ 0, 5, -1, -5, 0, 1 ], [ 1, 6, -1, -5, 0, 1 ], [ 0, 6, -1, -5, 0, 1 ] ], 1 ] - ], - [ - [ [ [ 0, 4, -1, -5, 0, 1 ], [ 0, 5, -1, -5, 0, 1 ], [ 1, 6, -1, -5, 0, 1 ], [ 2, 4, -1, -5, 0, 0 ] ], 1 ], - [ [ [ 0, 4, -1, -5, 0, 1 ], [ 1, 4, -2, -5, 0, 1 ], [ 1, 6, -1, -5, 0, 1 ], [ 2, 4, -1, -5, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 4, -1, -5, 0, 1 ], [ 1, 4, -2, -5, 0, 1 ], [ 1, 6, -1, -5, 0, 1 ], [ 1, 6, -1, -5, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 4, -1, -5, 0, 1 ], [ 1, 5, -1, -5, 0, 0 ], [ 1, 6, -1, -5, 0, 1 ], [ 1, 6, -1, -5, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 4, -1, -5, 0, 1 ], [ 1, 4, -1, -5, 0, 1 ], [ 1, 6, -1, -5, 0, 1 ], [ 1, 6, -1, -5, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 5, -1, -5, 0, 1 ], [ 1, 4, -1, -5, 0, 1 ], [ 1, 6, -1, -5, 0, 1 ], [ 1, 6, -1, -5, 0, 0 ] ], 1 ], - [ [ [ -1, 5, -1, -5, 0, 1 ], [ 1, 4, -1, -5, 0, 1 ], [ 3, 4, -1, -5, 0, 0 ], [ 1, 6, -1, -5, 0, 0 ] ], 1 ], - [ [ [ -1, 5, -1, -5, 0, 1 ], [ 1, 4, -1, -5, 0, 1 ], [ 3, 4, -1, -5, 0, 0 ], [ 1, 5, -1, -5, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -1, 5, -1, -5, 0, 1 ], [ 1, 5, -1, -5, -1, 1 ], [ 3, 4, -1, -5, 0, 0 ], [ 1, 5, -1, -5, 0, 1 ] ], 1 ], - [ [ [ 0, 4, -1, -5, 1, 0 ], [ 1, 5, -1, -5, -1, 1 ], [ 3, 4, -1, -5, 0, 0 ], [ 1, 5, -1, -5, 0, 1 ] ], 1 ] - ], - [ - [ [ [ 0, 4, -1, -5, 1, 0 ], [ 1, 5, -1, -5, -1, 1 ], [ 2, 4, -1, -5, -1, 1 ], [ 1, 5, -1, -5, 0, 1 ] ], 1 ], - [ [ [ 0, 4, -1, -5, 1, 0 ], [ 1, 5, -1, -5, -1, 1 ], [ 2, 4, -1, -5, -1, 1 ], [ 0, 5, -1, -4, -1, 1 ] ], 1 ], - [ [ [ -1, 5, -1, -4, -1, 1 ], [ 1, 5, -1, -5, -1, 1 ], [ 2, 4, -1, -5, -1, 1 ], [ 0, 5, -1, -4, -1, 1 ] ], 1 ] - ], - [ - [ [ [ -1, 5, -1, -4, -1, 1 ], [ 1, 5, -1, -5, -1, 1 ], [ 2, 4, -1, -5, -1, 1 ], [ -1, 5, -1, -3, -1, 1 ] ], 1 ], - [ [ [ -1, 5, -1, -4, -1, 1 ], [ 1, 5, -1, -5, -1, 1 ], [ 0, 5, -1, -3, -1, 1 ], [ -1, 5, -1, -3, -1, 1 ] ], 1 ] - ], - [ - [ [ [ -1, 5, -1, -4, -1, 1 ], [ 1, 5, -1, -5, -1, 1 ], [ 1, 5, -1, -4, -1, 1 ], [ -1, 5, -1, -3, -1, 1 ] ], 1 ], - [ [ [ -1, 5, -1, -4, -1, 1 ], [ 1, 5, -1, -5, -1, 1 ], [ 1, 5, -1, -4, -1, 1 ], [ 0, 5, -1, -4, -1, 1 ] ], 1 ] - ], - [ - [ [ [ -1, 5, -1, -4, -1, 1 ], [ 1, 5, -1, -5, -1, 1 ], [ 2, 5, -1, -5, -1, 1 ], [ 0, 5, -1, -4, -1, 1 ] ], 1 ] - ], - [ - [ [ [ -1, 5, -1, -4, -1, 1 ], [ 1, 5, -1, -5, -1, 1 ], [ 2, 5, -1, -5, -1, 1 ], [ 1, 6, -1, -5, -1, 1 ] ], 1 ], - [ [ [ 0, 5, -1, -5, -1, 1 ], [ 1, 5, -1, -5, -1, 1 ], [ 2, 5, -1, -5, -1, 1 ], [ 1, 6, -1, -5, -1, 1 ] ], 1 ], - [ [ [ 0, 5, -1, -5, -1, 1 ], [ 1, 5, -1, -5, -1, 1 ], [ 2, 5, -1, -5, -2, 1 ], [ 1, 6, -1, -5, -1, 1 ] ], 1 ] - ], - [ - [ [ [ 0, 5, -1, -5, -1, 1 ], [ 1, 6, -1, -5, -2, 1 ], [ 2, 5, -1, -5, -2, 1 ], [ 1, 6, -1, -5, -1, 1 ] ], 1 ] - ], - [ - [ [ [ 0, 6, -1, -5, -2, 1 ], [ 1, 6, -1, -5, -2, 1 ], [ 2, 5, -1, -5, -2, 1 ], [ 1, 6, -1, -5, -1, 1 ] ], 1 ] - ], - [ - [ [ [ 0, 6, -1, -5, -2, 1 ], [ 0, 6, -1, -5, -1, 1 ], [ 2, 5, -1, -5, -2, 1 ], [ 1, 6, -1, -5, -1, 1 ] ], 1 ], - [ [ [ 0, 6, -2, -5, -1, 1 ], [ 0, 6, -1, -5, -1, 1 ], [ 2, 5, -1, -5, -2, 1 ], [ 1, 6, -1, -5, -1, 1 ] ], 1 ], - [ [ [ 0, 6, -2, -5, -1, 1 ], [ 0, 6, -1, -5, -1, 1 ], [ 1, 6, -2, -5, -1, 1 ], [ 1, 6, -1, -5, -1, 1 ] ], 1 ] - ], - [ - [ [ [ 0, 6, -2, -5, -1, 1 ], [ 0, 6, -1, -5, -1, 1 ], [ 1, 6, -2, -5, -1, 1 ], [ 2, 5, -2, -5, -1, 1 ] ], 1 ], - [ [ [ -1, 7, -2, -5, -1, 1 ], [ 0, 6, -1, -5, -1, 1 ], [ 1, 6, -2, -5, -1, 1 ], [ 2, 5, -2, -5, -1, 1 ] ], 1 ] - ], - [ - [ [ [ -1, 7, -2, -5, -1, 1 ], [ 0, 6, -1, -5, -1, 1 ], [ 1, 6, -2, -5, -1, 1 ], [ 0, 7, -2, -5, -1, 1 ] ], 1 ], - [ [ [ -1, 7, -2, -5, -1, 1 ], [ 0, 6, -1, -5, -1, 1 ], [ 1, 5, -1, -5, -1, 1 ], [ 0, 7, -2, -5, -1, 1 ] ], 1 ] - ], - [ - [ [ [ -1, 7, -2, -5, -1, 1 ], [ -1, 8, -2, -5, -1, 1 ], [ 1, 5, -1, -5, -1, 1 ], [ 0, 7, -2, -5, -1, 1 ] ], 1 ], - [ [ [ -1, 7, -2, -5, -1, 1 ], [ -1, 8, -2, -5, -1, 1 ], [ 0, 8, -2, -5, -1, 1 ], [ 0, 7, -2, -5, -1, 1 ] ], 1 ] - ], - [ - [ [ [ -2, 8, -2, -5, -1, 1 ], [ -1, 8, -2, -5, -1, 1 ], [ 0, 8, -2, -5, -1, 1 ], [ 0, 7, -2, -5, -1, 1 ] ], 1 ], - [ [ [ -2, 8, -2, -5, -1, 1 ], [ 0, 8, -2, -6, -1, 1 ], [ 0, 8, -2, -5, -1, 1 ], [ 0, 7, -2, -5, -1, 1 ] ], 1 ], - [ [ [ -2, 8, -2, -5, -1, 1 ], [ 0, 8, -2, -6, -1, 1 ], [ 0, 8, -2, -5, -1, 1 ], [ -1, 9, -2, -5, -1, 1 ] ], 1 ] - ], - [ - [ [ [ -1, 8, -2, -6, -1, 1 ], [ 0, 8, -2, -6, -1, 1 ], [ 0, 8, -2, -5, -1, 1 ], [ -1, 9, -2, -5, -1, 1 ] ], 1 ], - [ [ [ -1, 8, -2, -6, -1, 1 ], [ 0, 8, -2, -6, -1, 1 ], [ 0, 8, -2, -5, -1, 1 ], [ 0, 8, -3, -5, -1, 1 ] ], 1 ] - ], - [ - [ [ [ -1, 8, -2, -6, -1, 1 ], [ 0, 8, -2, -6, -1, 1 ], [ 1, 8, -2, -6, -1, 1 ], [ 0, 8, -3, -5, -1, 1 ] ], 1 ] - ], - [ - [ [ [ -1, 8, -2, -6, -1, 1 ], [ 0, 8, -2, -6, -1, 1 ], [ 0, 9, -3, -5, -1, 1 ], [ 0, 8, -3, -5, -1, 1 ] ], 1 ], - [ [ [ -2, 8, -3, -5, -1, 2 ], [ 0, 8, -2, -6, -1, 1 ], [ 0, 9, -3, -5, -1, 1 ], [ 0, 8, -3, -5, -1, 1 ] ], 1 ], - [ [ [ -2, 8, -3, -5, -1, 2 ], [ -1, 8, -3, -5, -1, 2 ], [ 0, 9, -3, -5, -1, 1 ], [ 0, 8, -3, -5, -1, 1 ] ], 1 ] - ], - [ - [ [ [ -2, 8, -3, -5, -1, 2 ], [ -1, 8, -3, -5, -1, 2 ], [ 0, 8, -3, -5, -1, 2 ], [ 0, 8, -3, -5, -1, 1 ] ], 1 ], - [ [ [ -2, 8, -3, -5, -1, 2 ], [ -1, 8, -3, -5, -1, 2 ], [ 0, 8, -3, -5, -1, 2 ], [ 0, 7, -3, -5, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -2, 8, -3, -5, -1, 2 ], [ -1, 8, -3, -5, -1, 2 ], [ 1, 8, -3, -6, -1, 2 ], [ 0, 7, -3, -5, -1, 2 ] ], 1 ], - [ [ [ -1, 8, -3, -6, -1, 2 ], [ -1, 8, -3, -5, -1, 2 ], [ 1, 8, -3, -6, -1, 2 ], [ 0, 7, -3, -5, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -1, 7, -3, -6, -1, 2 ], [ -1, 8, -3, -5, -1, 2 ], [ 1, 8, -3, -6, -1, 2 ], [ 0, 7, -3, -5, -1, 2 ] ], 1 ], - [ [ [ -1, 7, -3, -6, -1, 2 ], [ -1, 8, -3, -5, -1, 2 ], [ -1, 8, -2, -5, -1, 2 ], [ 0, 7, -3, -5, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -1, 7, -3, -6, -1, 2 ], [ -2, 8, -2, -4, -1, 2 ], [ -1, 8, -2, -5, -1, 2 ], [ 0, 7, -3, -5, -1, 2 ] ], 1 ], - [ [ [ -2, 7, -2, -5, -1, 2 ], [ -2, 8, -2, -4, -1, 2 ], [ -1, 8, -2, -5, -1, 2 ], [ 0, 7, -3, -5, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -2, 7, -2, -5, -1, 2 ], [ -2, 8, -1, -5, -1, 2 ], [ -1, 8, -2, -5, -1, 2 ], [ 0, 7, -3, -5, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -2, 7, -2, -5, -1, 2 ], [ -1, 7, -2, -5, -1, 2 ], [ -1, 8, -2, -5, -1, 2 ], [ 0, 7, -3, -5, -1, 2 ] ], 1 ], - [ [ [ -3, 9, -2, -5, -1, 2 ], [ -1, 7, -2, -5, -1, 2 ], [ -1, 8, -2, -5, -1, 2 ], [ 0, 7, -3, -5, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -3, 9, -2, -5, -1, 2 ], [ 0, 6, -3, -5, -1, 2 ], [ -1, 8, -2, -5, -1, 2 ], [ 0, 7, -3, -5, -1, 2 ] ], 1 ], - [ [ [ -3, 9, -2, -5, -1, 2 ], [ 0, 6, -3, -5, -1, 2 ], [ -1, 8, -3, -5, -1, 2 ], [ 0, 7, -3, -5, -1, 2 ] ], 1 ], - [ [ [ -2, 8, -3, -5, -1, 2 ], [ 0, 6, -3, -5, -1, 2 ], [ -1, 8, -3, -5, -1, 2 ], [ 0, 7, -3, -5, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -2, 7, -3, -5, -1, 2 ], [ 0, 6, -3, -5, -1, 2 ], [ -1, 8, -3, -5, -1, 2 ], [ 0, 7, -3, -5, -1, 2 ] ], 1 ], - [ [ [ -2, 7, -3, -5, -1, 2 ], [ 0, 6, -3, -5, -1, 2 ], [ 0, 7, -4, -5, -1, 2 ], [ 0, 7, -3, -5, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -1, 7, -3, -6, -1, 2 ], [ 0, 6, -3, -5, -1, 2 ], [ 0, 7, -4, -5, -1, 2 ], [ 0, 7, -3, -5, -1, 2 ] ], 1 ], - [ [ [ -1, 7, -3, -6, -1, 2 ], [ -1, 8, -3, -5, -1, 2 ], [ 0, 7, -4, -5, -1, 2 ], [ 0, 7, -3, -5, -1, 2 ] ], 1 ], - [ [ [ -1, 7, -3, -6, -1, 2 ], [ -1, 8, -3, -5, -1, 2 ], [ -1, 7, -3, -4, -1, 2 ], [ 0, 7, -3, -5, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -1, 7, -3, -6, -1, 2 ], [ -1, 8, -3, -5, -1, 2 ], [ -1, 7, -3, -4, -1, 2 ], [ -1, 7, -2, -4, -1, 2 ] ], 1 ], - [ [ [ -1, 7, -3, -6, -1, 2 ], [ -1, 6, -3, -4, -1, 2 ], [ -1, 7, -3, -4, -1, 2 ], [ -1, 7, -2, -4, -1, 2 ] ], 1 ], - [ [ [ -2, 6, -3, -4, -1, 2 ], [ -1, 6, -3, -4, -1, 2 ], [ -1, 7, -3, -4, -1, 2 ], [ -1, 7, -2, -4, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -2, 6, -3, -4, -1, 2 ], [ -1, 6, -3, -4, -1, 2 ], [ 0, 6, -4, -4, -1, 2 ], [ -1, 7, -2, -4, -1, 2 ] ], 1 ], - [ [ [ -1, 6, -3, -5, -1, 2 ], [ -1, 6, -3, -4, -1, 2 ], [ 0, 6, -4, -4, -1, 2 ], [ -1, 7, -2, -4, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -1, 6, -3, -5, -1, 2 ], [ -1, 6, -3, -4, -1, 2 ], [ -1, 6, -3, -3, -1, 2 ], [ -1, 7, -2, -4, -1, 2 ] ], 1 ], - [ [ [ -1, 5, -3, -4, -1, 2 ], [ -1, 6, -3, -4, -1, 2 ], [ -1, 6, -3, -3, -1, 2 ], [ -1, 7, -2, -4, -1, 2 ] ], 1 ], - [ [ [ -1, 5, -3, -4, -1, 2 ], [ -1, 6, -3, -4, -1, 2 ], [ -1, 6, -3, -3, -1, 2 ], [ 0, 6, -3, -4, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -1, 5, -3, -4, -1, 2 ], [ 0, 5, -4, -4, -1, 2 ], [ -1, 6, -3, -3, -1, 2 ], [ 0, 6, -3, -4, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -1, 5, -3, -4, -1, 2 ], [ 0, 5, -4, -4, -1, 2 ], [ 0, 5, -3, -4, -1, 2 ], [ 0, 6, -3, -4, -1, 2 ] ], 1 ], - [ [ [ -1, 5, -3, -4, -1, 2 ], [ 0, 5, -4, -4, -1, 2 ], [ 0, 5, -3, -4, -1, 2 ], [ 1, 5, -4, -4, -1, 2 ] ], 1 ], - [ [ [ -1, 5, -3, -4, -1, 2 ], [ -1, 5, -3, -3, -1, 2 ], [ 0, 5, -3, -4, -1, 2 ], [ 1, 5, -4, -4, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -1, 5, -3, -4, -1, 2 ], [ 1, 5, -3, -4, -1, 2 ], [ 0, 5, -3, -4, -1, 2 ], [ 1, 5, -4, -4, -1, 2 ] ], 1 ], - [ [ [ -1, 5, -3, -4, -1, 2 ], [ 1, 5, -3, -4, -1, 2 ], [ 0, 5, -3, -4, -1, 2 ], [ 0, 5, -2, -4, -1, 2 ] ], 1 ], - [ [ [ -1, 5, -3, -4, -1, 2 ], [ 1, 5, -3, -4, -1, 2 ], [ 1, 5, -3, -5, -1, 2 ], [ 0, 5, -2, -4, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -1, 5, -3, -4, -1, 2 ], [ 1, 5, -3, -4, -1, 2 ], [ 1, 4, -3, -4, -1, 2 ], [ 0, 5, -2, -4, -1, 2 ] ], 1 ], - [ [ [ -1, 5, -3, -4, -1, 2 ], [ 1, 5, -3, -4, -1, 2 ], [ 1, 4, -3, -4, -1, 2 ], [ 0, 5, -3, -4, -1, 2 ] ], 1 ], - [ [ [ -1, 5, -3, -4, -1, 2 ], [ 0, 6, -3, -4, -1, 2 ], [ 1, 4, -3, -4, -1, 2 ], [ 0, 5, -3, -4, -1, 2 ] ], 1 ] - ], - [ - [ [ [ 0, 4, -4, -4, -1, 2 ], [ 0, 6, -3, -4, -1, 2 ], [ 1, 4, -3, -4, -1, 2 ], [ 0, 5, -3, -4, -1, 2 ] ], 1 ], - [ [ [ 0, 4, -4, -4, -1, 2 ], [ 1, 4, -4, -4, -1, 2 ], [ 1, 4, -3, -4, -1, 2 ], [ 0, 5, -3, -4, -1, 2 ] ], 1 ], - [ [ [ 0, 4, -4, -4, -1, 2 ], [ 1, 4, -4, -4, -1, 2 ], [ 1, 4, -3, -4, -1, 2 ], [ 2, 4, -4, -4, -1, 2 ] ], 1 ] - ], - [ - [ [ [ 0, 3, -3, -4, -1, 2 ], [ 1, 4, -4, -4, -1, 2 ], [ 1, 4, -3, -4, -1, 2 ], [ 2, 4, -4, -4, -1, 2 ] ], 1 ] - ], - [ - [ [ [ 0, 3, -4, -4, -1, 2 ], [ 1, 4, -4, -4, -1, 2 ], [ 1, 4, -3, -4, -1, 2 ], [ 2, 4, -4, -4, -1, 2 ] ], 1 ] - ], - [ - [ [ [ 0, 4, -3, -5, -1, 2 ], [ 1, 4, -4, -4, -1, 2 ], [ 1, 4, -3, -4, -1, 2 ], [ 2, 4, -4, -4, -1, 2 ] ], 1 ] - ], - [ - [ [ [ 0, 4, -3, -5, -1, 2 ], [ 1, 4, -4, -4, -1, 2 ], [ 1, 4, -3, -4, -1, 2 ], [ 1, 4, -3, -3, -1, 2 ] ], 1 ], - [ [ [ -1, 4, -2, -4, -1, 2 ], [ 1, 4, -4, -4, -1, 2 ], [ 1, 4, -3, -4, -1, 2 ], [ 1, 4, -3, -3, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -1, 4, -2, -4, -1, 2 ], [ 1, 4, -4, -4, -1, 2 ], [ 1, 4, -3, -4, -1, 2 ], [ 1, 5, -2, -4, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -1, 4, -2, -4, -1, 2 ], [ 1, 4, -4, -4, -1, 2 ], [ 1, 4, -3, -4, -1, 2 ], [ 1, 4, -2, -4, -1, 2 ] ], 1 ], - [ [ [ -1, 4, -2, -4, -1, 2 ], [ 1, 4, -4, -4, -1, 2 ], [ 2, 3, -4, -4, -1, 2 ], [ 1, 4, -2, -4, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -1, 4, -2, -4, -1, 2 ], [ 1, 4, -4, -4, -1, 2 ], [ 2, 3, -4, -4, -1, 2 ], [ 1, 3, -2, -4, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -1, 4, -2, -4, -1, 2 ], [ 1, 4, -4, -4, -1, 2 ], [ 2, 3, -4, -4, -1, 2 ], [ 1, 4, -2, -5, -1, 2 ] ], 1 ], - [ [ [ -1, 4, -2, -4, -1, 2 ], [ 0, 4, -2, -4, 0, 2 ], [ 2, 3, -4, -4, -1, 2 ], [ 1, 4, -2, -5, -1, 2 ] ], 1 ], - [ [ [ -1, 4, -2, -4, -1, 2 ], [ 0, 4, -2, -4, 0, 2 ], [ 0, 5, -2, -4, -1, 2 ], [ 1, 4, -2, -5, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -1, 4, -2, -4, -1, 2 ], [ 0, 4, -2, -4, 0, 2 ], [ 1, 4, -2, -4, 0, 1 ], [ 1, 4, -2, -5, -1, 2 ] ], 1 ], - [ [ [ -1, 4, -2, -4, -1, 2 ], [ 0, 4, -2, -4, 0, 2 ], [ 1, 4, -2, -4, 0, 1 ], [ 1, 4, -2, -4, -1, 1 ] ], 1 ] - ], - [ - [ [ [ 0, 3, -2, -4, 0, 1 ], [ 0, 4, -2, -4, 0, 2 ], [ 1, 4, -2, -4, 0, 1 ], [ 1, 4, -2, -4, -1, 1 ] ], 1 ] - ], - [ - [ [ [ -1, 4, -2, -4, 0, 1 ], [ 0, 4, -2, -4, 0, 2 ], [ 1, 4, -2, -4, 0, 1 ], [ 1, 4, -2, -4, -1, 1 ] ], 1 ], - [ [ [ -1, 4, -2, -4, 0, 1 ], [ 0, 4, -2, -4, 0, 2 ], [ 1, 4, -2, -4, 0, 1 ], [ 0, 4, -3, -4, 0, 2 ] ], 1 ], - [ [ [ -1, 4, -2, -4, 0, 1 ], [ 0, 4, -2, -4, 0, 2 ], [ 1, 3, -2, -4, 0, 2 ], [ 0, 4, -3, -4, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -1, 4, -2, -4, 0, 1 ], [ 0, 4, -2, -4, 0, 2 ], [ 0, 5, -2, -4, 0, 2 ], [ 0, 4, -3, -4, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -1, 3, -2, -4, 0, 2 ], [ 0, 4, -2, -4, 0, 2 ], [ 0, 5, -2, -4, 0, 2 ], [ 0, 4, -3, -4, 0, 2 ] ], 1 ], - [ [ [ -1, 3, -2, -4, 0, 2 ], [ "Rest" ], [ 0, 5, -2, -4, 0, 2 ], [ 0, 4, -3, -4, 0, 2 ] ], 1 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 5, -2, -4, 0, 2 ], [ 0, 4, -3, -4, 0, 2 ] ], 1 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 0, 4, -3, -4, 0, 2 ] ], 1 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1 ] - ] - ] -], -"last_changes": -[ - [ [ -1, 4, -2, -4, 0, 1 ], [ 0, 4, -2, -4, 0, 2 ], [ 1, 4, -2, -4, 0, 1 ], [ 1, 4, -2, -4, -1, 1 ] ], - [ [ -1, 4, -2, -4, 0, 1 ], [ 0, 4, -2, -4, 0, 2 ], [ 1, 4, -2, -4, 0, 1 ], [ 0, 4, -3, -4, 0, 2 ] ], - [ [ -1, 4, -2, -4, 0, 1 ], [ 0, 4, -2, -4, 0, 2 ], [ 1, 3, -2, -4, 0, 2 ], [ 0, 4, -3, -4, 0, 2 ] ], - [ [ -1, 4, -2, -4, 0, 1 ], [ 0, 4, -2, -4, 0, 2 ], [ 0, 5, -2, -4, 0, 2 ], [ 0, 4, -3, -4, 0, 2 ] ], - [ [ -1, 3, -2, -4, 0, 2 ], [ 0, 4, -2, -4, 0, 2 ], [ 0, 5, -2, -4, 0, 2 ], [ 0, 4, -3, -4, 0, 2 ] ] -], -"cur_uid": "4ff624b0", -"ref_uid": "nil", -"order_seed": 492048, -"dur_seed": 518010, -"motifs_seed": 626337, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ -1200, 1200, 0.0020576131687243, 0.068181818181818, 0.074074074074074, 0.0625, 0.20576131687243, 0.0625, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61316872427983, 0, 0.98971193415638, 0 ], -"passages_weights": [ 0.48, 0.46, 0.48, 1, 1 ], -"hd_exp": 9, -"hd_invert": 0, -"order": -[ - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 1, 2 ], [ 0, 3 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 2 ], [ 3, 0, 1 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ], - [ [ 1 ], [ 0, 2, 3 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 0, 1 ], [ 3, 2 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 2 ], [ 3, 0, 1 ], [ ] ], - [ [ 3, 1 ], [ 2, 0 ], [ ] ], - [ [ 3, 0 ], [ 1, 2 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 2, 3 ], [ 1, 0 ], [ ] ], - [ [ 2, 0 ], [ 3, 1 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ], - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 3 ], [ 0, 2, 1 ], [ ] ], - [ [ 1, 3 ], [ 0, 2 ], [ ] ], - [ [ 2 ], [ 3, 1, 0 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 3, 0 ], [ 2, 1 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 0 ], [ 1, 2, 3 ], [ ] ], - [ [ 1, 3 ], [ 0, 2 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 1 ], [ 2, 0, 3 ], [ ] ], - [ [ 1, 3, 2 ], [ 0 ], [ ] ], - [ [ 1, 0 ], [ 3, 2 ], [ ] ], - [ [ 1 ], [ 3, 2, 0 ], [ ] ], - [ [ 2 ], [ 0, 1, 3 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 3, 2 ], [ 1, 0 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 2 ], [ 0, 1, 3 ], [ ] ], - [ [ 3, 2 ], [ 1, 0 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 3 ], [ 1, 0, 2 ], [ ] ], - [ [ 1, 0 ], [ 3, 2 ], [ ] ], - [ [ 0, 2 ], [ 3, 1 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 1 ], [ 0, 2, 3 ], [ ] ], - [ [ 3, 2 ], [ 1, 0 ], [ ] ], - [ [ 1 ], [ 2, 3, 0 ], [ ] ], - [ [ 1, 0 ], [ 3, 2 ], [ ] ], - [ [ 1, 0 ], [ 2, 3 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 3 ], [ 1, 0, 2 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 1, 0 ], [ 3, 2 ], [ ] ], - [ [ 0, 3 ], [ 1, 2 ], [ ] ], - [ [ 2 ], [ 0, 1, 3 ], [ ] ], - [ [ 1, 2 ], [ 0, 3 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 3 ], [ 2, 0, 1 ], [ ] ], - [ [ 1, 0 ], [ 2, 3 ], [ ] ], - [ [ 1, 3 ], [ 2, 0 ], [ ] ], - [ [ 1, 3 ], [ 0, 2 ], [ ] ], - [ [ 3, 2 ], [ 1, 0 ], [ ] ], - [ [ 2, 0, 3 ], [ 1 ], [ ] ], - [ [ 3, 2 ], [ 1, 0 ], [ ] ], - [ [ 3 ], [ 1, 2, 0 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 3 ], [ 0, 1, 2 ], [ ] ], - [ [ 2 ], [ 3, 1, 0 ], [ ] ], - [ [ 1, 3 ], [ 2, 0 ], [ ] ], - [ [ 1 ], [ 2, 0, 3 ], [ ] ], - [ [ 2, 0, 3 ], [ 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 2 ], [ 0, 1, 3 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 1, 0 ], [ 3, 2 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 1, 0 ], [ 2, 3 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 1 ], [ 0, 3, 2 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 100, 100 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/5201b8af_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/5201b8af_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/5201b8af_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/5201b8af_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/5201b8af_mus_model.json deleted file mode 100644 index aa90760..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/5201b8af_mus_model.json +++ /dev/null @@ -1,58 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 4.875 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 0, 1, 0, 0, 0 ] ], 4.75 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 4.125 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ], - [ [ [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], - [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ] -], -"cur_uid": "5201b8af", -"ref_uid": "77b0d2dc", -"order_seed": 921767, -"dur_seed": 954688, -"motifs_seed": 995213, -"entrances_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 0, 3.68, 5, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315.1702786378, 338.08049535604 ], [ -200.61919504644, 1452.6315789474 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 8, 10 ], -"passages_size": [ 0, 10 ], -"motif_edited": "true", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/lilypond/part_I.ly deleted file mode 100644 index 01ab702..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/lilypond/part_I.ly +++ /dev/null @@ -1,16 +0,0 @@ -{ - { r2 c''2^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''2. ~ c''8.[ e'16^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}] ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'4 ~ e'16[ e'8.^\markup { \pad-markup #0.2 "-41"}] ~ e'2 ~ } - \bar "|" - { e'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/lilypond/part_II.ly deleted file mode 100644 index f176e75..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/lilypond/part_II.ly +++ /dev/null @@ -1,16 +0,0 @@ -{ - { r2 e'2^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'2. ~ e'8.[ e'16^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'4 ~ e'16[ f'8.^\markup { \pad-markup #0.2 "-2"}] ~ f'2 ~ } - \bar "|" - { f'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/lilypond/part_III.ly deleted file mode 100644 index 5f83063..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/lilypond/part_III.ly +++ /dev/null @@ -1,16 +0,0 @@ -{ - { r2 fis'2^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }} ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'2. ~ fis'8.[ g'16^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'4 ~ g'16[ gis'8.^\markup { \pad-markup #0.2 "+14"}] ~ gis'2 ~ } - \bar "|" - { gis'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/lilypond/part_IV.ly deleted file mode 100644 index 67fc5d0..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/5201b8af/lilypond/part_IV.ly +++ /dev/null @@ -1,16 +0,0 @@ -{ - { c'1^\markup { \pad-markup #0.2 "+0"} ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/5488f7e9/5488f7e9_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3/5488f7e9/5488f7e9_code.scd deleted file mode 100644 index e5197a1..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/5488f7e9/5488f7e9_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - if(pDistance < 0, {stepFunc.value(pDistance)}, {0.001}); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/5488f7e9/5488f7e9_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3/5488f7e9/5488f7e9_mus_model.json deleted file mode 100644 index cf2a424..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/5488f7e9/5488f7e9_mus_model.json +++ /dev/null @@ -1,163 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ -3, -2, 0, 1, 0, -2 ], [ "Rest" ], [ "Rest" ] ], 0.75 ], - [ [ [ "Rest" ], [ -3, -2, 0, 1, 0, -2 ], [ -3, -1, 0, 0, 0, -1 ], [ "Rest" ] ], 0.75 ], - [ [ [ -3, -1, 0, 1, 0, -2 ], [ -3, -2, 0, 1, 0, -2 ], [ -3, -1, 0, 0, 0, -1 ], [ "Rest" ] ], 0.5 ], - [ [ [ -3, -1, 0, 1, 0, -2 ], [ -3, -2, 0, 1, 0, -2 ], [ -3, -1, 0, 0, 0, -1 ], [ 0, -1, 0, 2, 0, -2 ] ], 0.5 ] - ], - [ - [ [ [ -3, -1, 0, 1, 0, -2 ], [ 0, -1, 0, 1, 0, -1 ], [ -3, -1, 0, 0, 0, -1 ], [ 0, -1, 0, 2, 0, -2 ] ], 0.75 ] - ], - [ - [ [ [ -3, -1, 0, 1, 0, -2 ], [ 2, -1, 0, 2, -1, -2 ], [ -3, -1, 0, 0, 0, -1 ], [ 0, -1, 0, 2, 0, -2 ] ], 0.5 ] - ], - [ - [ [ [ -3, -1, 0, 1, 0, -2 ], [ 2, -1, 0, 2, -1, -2 ], [ 2, -1, 0, 1, 0, -2 ], [ 0, -1, 0, 2, 0, -2 ] ], 0.875 ] - ], - [ - [ [ [ 0, 0, 0, 1, 0, -2 ], [ 2, -1, 0, 2, -1, -2 ], [ 2, -1, 0, 1, 0, -2 ], [ 0, -1, 0, 2, 0, -2 ] ], 0.5 ] - ], - [ - [ [ [ 0, 0, 0, 1, 0, -2 ], [ 2, -1, 0, 2, -1, -2 ], [ 2, -1, 0, 1, 0, -2 ], [ 1, 0, 0, 1, 0, -2 ] ], 0.5 ] - ], - [ - [ [ [ 0, 0, 0, 1, 0, -2 ], [ 2, -1, 0, 2, -1, -2 ], [ 2, -1, 0, 1, 0, -2 ], [ 0, 0, 0, 2, 0, -2 ] ], 1.25 ] - ], - [ - [ [ [ 0, 0, 0, 1, 0, -2 ], [ 2, -1, 0, 2, -1, -2 ], [ 2, -1, 0, 1, 0, -2 ], [ 1, 1, 0, 1, 0, -2 ] ], 0.875 ] - ], - [ - [ [ [ 0, 0, 0, 1, 0, -2 ], [ 2, 0, 0, 1, -1, -2 ], [ 2, -1, 0, 1, 0, -2 ], [ 1, 1, 0, 1, 0, -2 ] ], 1.125 ] - ], - [ - [ [ [ 0, 0, 0, 1, 0, -2 ], [ 2, 0, 0, 1, -1, -2 ], [ 1, 1, 0, 1, 1, -2 ], [ 1, 1, 0, 1, 0, -2 ] ], 0.125 ] - ], - [ - [ [ [ 0, 0, 0, 1, 0, -2 ], [ 0, 1, 0, 1, -1, -2 ], [ 1, 1, 0, 1, 1, -2 ], [ 1, 1, 0, 1, 0, -2 ] ], 0.625 ] - ], - [ - [ [ [ 0, 0, 0, 1, 0, -2 ], [ 0, 1, 0, 1, -1, -2 ], [ 0, 1, -1, 1, 0, -2 ], [ 1, 1, 0, 1, 0, -2 ] ], 1.125 ] - ], - [ - [ [ [ 0, 0, 0, 1, 0, -2 ], [ 0, 1, 0, 1, -1, -2 ], [ 1, 0, 0, 0, 0, -2 ], [ 1, 1, 0, 1, 0, -2 ] ], 0.875 ] - ], - [ - [ [ [ 0, 0, 0, 1, 0, -2 ], [ 0, 1, 0, 1, 0, -3 ], [ 1, 0, 0, 0, 0, -2 ], [ 1, 1, 0, 1, 0, -2 ] ], 0.25 ] - ], - [ - [ [ [ 0, 0, 0, 1, 0, -2 ], [ 2, -1, 0, 1, 0, -2 ], [ 1, 0, 0, 0, 0, -2 ], [ 1, 1, 0, 1, 0, -2 ] ], 1.125 ] - ], - [ - [ [ [ 0, 0, 0, 1, 0, -2 ], [ 2, -1, 0, 1, 0, -2 ], [ 1, -1, 0, 1, -1, -2 ], [ 1, 1, 0, 1, 0, -2 ] ], 0.25 ] - ], - [ - [ [ [ 0, 0, 0, 1, 0, -2 ], [ 1, -1, 0, 2, -1, -2 ], [ 1, -1, 0, 1, -1, -2 ], [ 1, 1, 0, 1, 0, -2 ] ], 0.875 ] - ], - [ - [ [ [ 0, 1, 0, 1, 0, -1 ], [ 1, -1, 0, 2, -1, -2 ], [ 1, -1, 0, 1, -1, -2 ], [ 1, 1, 0, 1, 0, -2 ] ], 0.75 ] - ], - [ - [ [ [ 0, 1, 0, 1, 0, -1 ], [ 1, -1, 0, 2, -1, -2 ], [ -1, 1, 1, 1, 0, -2 ], [ 1, 1, 0, 1, 0, -2 ] ], 0.75 ] - ], - [ - [ [ [ 0, 1, 1, 1, 0, -3 ], [ 1, -1, 0, 2, -1, -2 ], [ -1, 1, 1, 1, 0, -2 ], [ 1, 1, 0, 1, 0, -2 ] ], 1 ] - ], - [ - [ [ [ 0, 1, 1, 1, 0, -3 ], [ 1, -1, 0, 2, -1, -2 ], [ 1, 1, 1, 1, -1, -3 ], [ 1, 1, 0, 1, 0, -2 ] ], 1.125 ] - ], - [ - [ [ [ 0, 1, 1, 1, 0, -3 ], [ 1, -1, 0, 2, -1, -2 ], [ 2, -1, 0, 2, -1, -3 ], [ 1, 1, 0, 1, 0, -2 ] ], 0.375 ] - ], - [ - [ [ [ 2, -1, 0, 3, -1, -3 ], [ 1, -1, 0, 2, -1, -2 ], [ 2, -1, 0, 2, -1, -3 ], [ 1, 1, 0, 1, 0, -2 ] ], 0.75 ] - ], - [ - [ [ [ 2, -1, 0, 3, -1, -3 ], [ 1, -1, 0, 2, -1, -2 ], [ 2, -1, 0, 2, -1, -3 ], [ 3, -1, 0, 1, -1, -2 ] ], 1.125 ] - ], - [ - [ [ [ 2, -1, 0, 3, -1, -3 ], [ 2, -2, 0, 3, -1, -3 ], [ 2, -1, 0, 2, -1, -3 ], [ 3, -1, 0, 1, -1, -2 ] ], 0.375 ] - ], - [ - [ [ [ 2, -1, 0, 3, -1, -3 ], [ 2, -2, 0, 3, -1, -3 ], [ 2, -1, 0, 2, -1, -3 ], [ 2, -2, 1, 3, -1, -3 ] ], 0.625 ] - ], - [ - [ [ [ 2, -1, 0, 3, -1, -3 ], [ 2, -2, 0, 3, -1, -3 ], [ 2, -1, 0, 2, -1, -3 ], [ 2, -2, 0, 2, -1, -3 ] ], 0.25 ] - ], - [ - [ [ [ 1, -1, -1, 2, -1, -3 ], [ 2, -2, 0, 3, -1, -3 ], [ 2, -1, 0, 2, -1, -3 ], [ 2, -2, 0, 2, -1, -3 ] ], 1.125 ] - ], - [ - [ [ [ 1, -1, -1, 2, -1, -3 ], [ 2, -2, 0, 3, -1, -3 ], [ 2, -1, 0, 2, -1, -3 ], [ 2, -1, -1, 2, -1, -2 ] ], 0.25 ] - ], - [ - [ [ [ 1, -1, -1, 2, -1, -3 ], [ 2, -1, -1, 3, -1, -3 ], [ 2, -1, 0, 2, -1, -3 ], [ 2, -1, -1, 2, -1, -2 ] ], 0.875 ], - [ [ [ "Rest" ], [ 2, -1, -1, 3, -1, -3 ], [ 2, -1, 0, 2, -1, -3 ], [ 2, -1, -1, 2, -1, -2 ] ], 0 ], - [ [ [ "Rest" ], [ 2, -1, -1, 3, -1, -3 ], [ 2, -1, 0, 2, -1, -3 ], [ "Rest" ] ], 0.5 ], - [ [ [ "Rest" ], [ "Rest" ], [ 2, -1, 0, 2, -1, -3 ], [ "Rest" ] ], 0.375 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 6.625 ] - ] - ] -], -"last_changes": -[ - [ [ 2, -1, 0, 3, -1, -3 ], [ 2, -2, 0, 3, -1, -3 ], [ 2, -1, 0, 2, -1, -3 ], [ 2, -2, 1, 3, -1, -3 ] ], - [ [ 2, -1, 0, 3, -1, -3 ], [ 2, -2, 0, 3, -1, -3 ], [ 2, -1, 0, 2, -1, -3 ], [ 2, -2, 0, 2, -1, -3 ] ], - [ [ 1, -1, -1, 2, -1, -3 ], [ 2, -2, 0, 3, -1, -3 ], [ 2, -1, 0, 2, -1, -3 ], [ 2, -2, 0, 2, -1, -3 ] ], - [ [ 1, -1, -1, 2, -1, -3 ], [ 2, -2, 0, 3, -1, -3 ], [ 2, -1, 0, 2, -1, -3 ], [ 2, -1, -1, 2, -1, -2 ] ], - [ [ 1, -1, -1, 2, -1, -3 ], [ 2, -1, -1, 3, -1, -3 ], [ 2, -1, 0, 2, -1, -3 ], [ 2, -1, -1, 2, -1, -2 ] ] -], -"cur_uid": "5488f7e9", -"ref_uid": "7c2de94c", -"order_seed": 199804, -"dur_seed": 927098, -"motifs_seed": 741655, -"entrances_probs_vals": [ 0, 0, 0, 0, 1.2087912087912, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 0, 1.2087912087912, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 0, 1.2087912087912, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1147.9876160991, 1638 ], [ -1240.866873065, 1453 ], [ -980.80495356037, 1768 ], [ -850.77399380805, 1843 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 1, 0.34, 0.98, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 2, 0, 3 ], [ 1 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 1, 3, 2 ], [ 0 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 2, 0, 3 ], [ 1 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ] -], -"sus_weights": [ 0, 0, 0.61 ], -"order_size": [ 30, 30 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/55bd25a1/55bd25a1_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3/55bd25a1/55bd25a1_code.scd deleted file mode 100644 index 49436ca..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/55bd25a1/55bd25a1_code.scd +++ /dev/null @@ -1,973 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - - - //isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/55bd25a1/55bd25a1_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3/55bd25a1/55bd25a1_mus_model.json deleted file mode 100644 index b0cec78..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/55bd25a1/55bd25a1_mus_model.json +++ /dev/null @@ -1,548 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ 7, -5, -2, -1, -3, -2 ], [ "Rest" ], [ "Rest" ] ], 1.125 ], - [ [ [ "Rest" ], [ 7, -5, -2, -1, -3, -2 ], [ "Rest" ], [ 6, -6, -2, 0, -1, -2 ] ], 1.25 ], - [ [ [ 5, -5, -2, 0, -2, -2 ], [ 7, -5, -2, -1, -3, -2 ], [ "Rest" ], [ 6, -6, -2, 0, -1, -2 ] ], 1.25 ], - [ [ [ 5, -5, -2, 0, -2, -2 ], [ 7, -5, -2, -1, -3, -2 ], [ 6, -5, -2, 0, -1, -2 ], [ 6, -6, -2, 0, -1, -2 ] ], 1.5 ] - ], - [ - [ [ [ 5, -5, -2, 0, -2, -2 ], [ 6, -6, -2, 0, -2, -2 ], [ 6, -5, -2, 0, -1, -2 ], [ 6, -6, -2, 0, -1, -2 ] ], 0.625 ], - [ [ [ 5, -5, -2, 0, -2, -2 ], [ 6, -6, -2, 0, -2, -2 ], [ 6, -4, -2, 0, -2, -2 ], [ 6, -6, -2, 0, -1, -2 ] ], 0.5 ] - ], - [ - [ [ [ 4, -3, -2, 0, -2, -2 ], [ 6, -6, -2, 0, -2, -2 ], [ 6, -4, -2, 0, -2, -2 ], [ 6, -6, -2, 0, -1, -2 ] ], 0.625 ], - [ [ [ 4, -3, -2, 0, -2, -2 ], [ 5, -4, -2, 0, -2, -2 ], [ 6, -4, -2, 0, -2, -2 ], [ 6, -6, -2, 0, -1, -2 ] ], 1 ] - ], - [ - [ [ [ 4, -3, -2, 0, -2, -2 ], [ 5, -4, -2, 0, -2, -2 ], [ 7, -4, -2, -1, -2, -2 ], [ 6, -6, -2, 0, -1, -2 ] ], 1 ], - [ [ [ 5, -4, -3, 0, -2, -2 ], [ 5, -4, -2, 0, -2, -2 ], [ 7, -4, -2, -1, -2, -2 ], [ 6, -6, -2, 0, -1, -2 ] ], 0.75 ], - [ [ [ 5, -4, -3, 0, -2, -2 ], [ 5, -4, -2, 0, -2, -2 ], [ 7, -4, -2, -1, -2, -2 ], [ 6, -5, -2, 0, -2, -2 ] ], 0.5 ] - ], - [ - [ [ [ 6, -6, -2, 0, -2, -2 ], [ 5, -4, -2, 0, -2, -2 ], [ 7, -4, -2, -1, -2, -2 ], [ 6, -5, -2, 0, -2, -2 ] ], 0.625 ], - [ [ [ 6, -6, -2, 0, -2, -2 ], [ 6, -5, -3, 0, -2, -2 ], [ 7, -4, -2, -1, -2, -2 ], [ 6, -5, -2, 0, -2, -2 ] ], 1.25 ], - [ [ [ 6, -6, -2, 0, -2, -2 ], [ 6, -5, -3, 0, -2, -2 ], [ 7, -5, -3, 0, -2, -2 ], [ 6, -5, -2, 0, -2, -2 ] ], 1.5 ] - ], - [ - [ [ [ 6, -6, -2, 0, -2, -2 ], [ 6, -5, -3, 0, -2, -2 ], [ 6, -5, -2, 1, -2, -2 ], [ 6, -5, -2, 0, -2, -2 ] ], 0.625 ] - ], - [ - [ [ [ 6, -5, -2, 0, -3, -2 ], [ 6, -5, -3, 0, -2, -2 ], [ 6, -5, -2, 1, -2, -2 ], [ 6, -5, -2, 0, -2, -2 ] ], 0.5 ], - [ [ [ 6, -5, -2, 0, -3, -2 ], [ 5, -5, -2, 1, -2, -2 ], [ 6, -5, -2, 1, -2, -2 ], [ 6, -5, -2, 0, -2, -2 ] ], 0.75 ], - [ [ [ 6, -5, -2, 0, -3, -2 ], [ 5, -5, -2, 1, -2, -2 ], [ 6, -4, -2, 0, -2, -2 ], [ 6, -5, -2, 0, -2, -2 ] ], 0.75 ] - ], - [ - [ [ [ 5, -5, -1, 0, -2, -2 ], [ 5, -5, -2, 1, -2, -2 ], [ 6, -4, -2, 0, -2, -2 ], [ 6, -5, -2, 0, -2, -2 ] ], 0.875 ], - [ [ [ 5, -5, -1, 0, -2, -2 ], [ 5, -4, -2, 0, -2, -2 ], [ 6, -4, -2, 0, -2, -2 ], [ 6, -5, -2, 0, -2, -2 ] ], 0.875 ], - [ [ [ 5, -5, -1, 0, -2, -2 ], [ 5, -4, -2, 0, -2, -2 ], [ 6, -5, -2, 0, -2, -1 ], [ 6, -5, -2, 0, -2, -2 ] ], 0.875 ] - ], - [ - [ [ [ 5, -5, -1, 0, -2, -2 ], [ 5, -4, -2, 0, -2, -2 ], [ 6, -5, -2, 0, -2, -1 ], [ 5, -5, -1, 1, -2, -2 ] ], 1.625 ], - [ [ [ 5, -5, -1, 0, -2, -2 ], [ 6, -6, -1, 0, -2, -2 ], [ 6, -5, -2, 0, -2, -1 ], [ 5, -5, -1, 1, -2, -2 ] ], 0.75 ] - ], - [ - [ [ [ 5, -5, -1, 0, -2, -2 ], [ 6, -6, -1, 0, -2, -2 ], [ 6, -5, -2, 0, -2, -1 ], [ 6, -5, -1, 0, -2, -2 ] ], 1.75 ] - ], - [ - [ [ [ 5, -5, -1, 0, -2, -2 ], [ 5, -4, -1, 0, -2, -2 ], [ 6, -5, -2, 0, -2, -1 ], [ 6, -5, -1, 0, -2, -2 ] ], 1.75 ], - [ [ [ 6, -5, -1, -1, -2, -2 ], [ 5, -4, -1, 0, -2, -2 ], [ 6, -5, -2, 0, -2, -1 ], [ 6, -5, -1, 0, -2, -2 ] ], 1.125 ], - [ [ [ 6, -5, -1, -1, -2, -2 ], [ 5, -4, -1, 0, -2, -2 ], [ 6, -4, -1, 0, -2, -2 ], [ 6, -5, -1, 0, -2, -2 ] ], 1.75 ] - ], - [ - [ [ [ 5, -4, -2, 0, -2, -2 ], [ 5, -4, -1, 0, -2, -2 ], [ 6, -4, -1, 0, -2, -2 ], [ 6, -5, -1, 0, -2, -2 ] ], 0.875 ], - [ [ [ 5, -4, -2, 0, -2, -2 ], [ 5, -4, -1, 0, -2, -2 ], [ 6, -4, -1, 0, -2, -2 ], [ 5, -3, -1, 0, -2, -2 ] ], 1.25 ], - [ [ [ 5, -4, -2, 0, -2, -2 ], [ 6, -4, -1, -1, -2, -2 ], [ 6, -4, -1, 0, -2, -2 ], [ 5, -3, -1, 0, -2, -2 ] ], 1 ] - ], - [ - [ [ [ 5, -5, -1, 0, -2, -2 ], [ 6, -4, -1, -1, -2, -2 ], [ 6, -4, -1, 0, -2, -2 ], [ 5, -3, -1, 0, -2, -2 ] ], 1.25 ] - ], - [ - [ [ [ 4, -3, -1, 0, -2, -2 ], [ 6, -4, -1, -1, -2, -2 ], [ 6, -4, -1, 0, -2, -2 ], [ 5, -3, -1, 0, -2, -2 ] ], 1.5 ], - [ [ [ 4, -3, -1, 0, -2, -2 ], [ 6, -4, -1, -1, -2, -2 ], [ 6, -4, -1, 0, -2, -2 ], [ 6, -4, -2, 0, -2, -2 ] ], 0.75 ] - ], - [ - [ [ [ 4, -3, -1, 0, -2, -2 ], [ 6, -4, -1, 0, -2, -3 ], [ 6, -4, -1, 0, -2, -2 ], [ 6, -4, -2, 0, -2, -2 ] ], 1.375 ] - ], - [ - [ [ [ 4, -3, -1, 0, -2, -2 ], [ 6, -4, -1, 0, -2, -3 ], [ 6, -4, -1, 0, -2, -2 ], [ 4, -4, -1, 1, -2, -2 ] ], 0.75 ], - [ [ [ 5, -4, -2, 0, -2, -2 ], [ 6, -4, -1, 0, -2, -3 ], [ 6, -4, -1, 0, -2, -2 ], [ 4, -4, -1, 1, -2, -2 ] ], 1.375 ], - [ [ [ 5, -4, -2, 0, -2, -2 ], [ 6, -5, -1, 0, -2, -2 ], [ 6, -4, -1, 0, -2, -2 ], [ 4, -4, -1, 1, -2, -2 ] ], 0.375 ] - ], - [ - [ [ [ 4, -4, -1, 1, -3, -2 ], [ 6, -5, -1, 0, -2, -2 ], [ 6, -4, -1, 0, -2, -2 ], [ 4, -4, -1, 1, -2, -2 ] ], 0.5 ], - [ [ [ 4, -4, -1, 1, -3, -2 ], [ 4, -4, -1, 1, -2, -1 ], [ 6, -4, -1, 0, -2, -2 ], [ 4, -4, -1, 1, -2, -2 ] ], 1.625 ], - [ [ [ 4, -4, -1, 1, -3, -2 ], [ 4, -4, -1, 1, -2, -1 ], [ 5, -4, -1, 1, -2, -2 ], [ 4, -4, -1, 1, -2, -2 ] ], 1.5 ] - ], - [ - [ [ [ 4, -4, -1, 1, -3, -2 ], [ 4, -4, -1, 1, -2, -1 ], [ 5, -4, -1, 1, -2, -2 ], [ 5, -4, -1, 0, -2, -2 ] ], 1.25 ], - [ [ [ 4, -4, -1, 1, -3, -2 ], [ 4, -4, -1, 1, -2, -2 ], [ 5, -4, -1, 1, -2, -2 ], [ 5, -4, -1, 0, -2, -2 ] ], 1.625 ], - [ [ [ 4, -4, -2, 1, -2, -2 ], [ 4, -4, -1, 1, -2, -2 ], [ 5, -4, -1, 1, -2, -2 ], [ 5, -4, -1, 0, -2, -2 ] ], 0.5 ] - ], - [ - [ [ [ 4, -4, -2, 1, -2, -2 ], [ 4, -4, -1, 1, -2, -2 ], [ 6, -4, -2, 0, -2, -2 ], [ 5, -4, -1, 0, -2, -2 ] ], 0.875 ], - [ [ [ 4, -4, -2, 1, -2, -2 ], [ 4, -4, -1, 1, -2, -2 ], [ 6, -4, -2, 0, -2, -2 ], [ 4, -4, 0, 1, -2, -2 ] ], 0.875 ] - ], - [ - [ [ [ 4, -4, -2, 1, -2, -2 ], [ 4, -4, -1, 1, -2, -2 ], [ 4, -4, 0, 1, -2, -1 ], [ 4, -4, 0, 1, -2, -2 ] ], 1.75 ], - [ [ [ 3, -4, -1, 2, -2, -2 ], [ 4, -4, -1, 1, -2, -2 ], [ 4, -4, 0, 1, -2, -1 ], [ 4, -4, 0, 1, -2, -2 ] ], 1.625 ] - ], - [ - [ [ [ 3, -4, -1, 2, -2, -2 ], [ 4, -4, -1, 1, -2, -2 ], [ 4, -4, 0, 1, -2, -1 ], [ 3, -4, -1, 2, -2, -1 ] ], 1.375 ], - [ [ [ 3, -4, -1, 2, -2, -2 ], [ 3, -4, 0, 2, -2, -2 ], [ 4, -4, 0, 1, -2, -1 ], [ 3, -4, -1, 2, -2, -1 ] ], 1.625 ], - [ [ [ 3, -4, -1, 2, -2, -2 ], [ 3, -4, 0, 2, -2, -2 ], [ 4, -4, 0, 2, -2, -2 ], [ 3, -4, -1, 2, -2, -1 ] ], 1.5 ] - ], - [ - [ [ [ 3, -5, -1, 2, -2, -1 ], [ 3, -4, 0, 2, -2, -2 ], [ 4, -4, 0, 2, -2, -2 ], [ 3, -4, -1, 2, -2, -1 ] ], 1 ], - [ [ [ 3, -5, -1, 2, -2, -1 ], [ 2, -4, -1, 2, -2, 0 ], [ 4, -4, 0, 2, -2, -2 ], [ 3, -4, -1, 2, -2, -1 ] ], 1.25 ] - ], - [ - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 2, -4, -1, 2, -2, 0 ], [ 4, -4, 0, 2, -2, -2 ], [ 3, -4, -1, 2, -2, -1 ] ], 1.25 ], - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 2, -4, 0, 2, -2, -1 ], [ 4, -4, 0, 2, -2, -2 ], [ 3, -4, -1, 2, -2, -1 ] ], 0.875 ] - ], - [ - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 2, -4, 0, 2, -2, -1 ], [ 4, -5, 0, 2, -2, -1 ], [ 3, -4, -1, 2, -2, -1 ] ], 1.75 ], - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 2, -4, 0, 2, -2, -1 ], [ 4, -5, 0, 2, -2, -1 ], [ 2, -4, 0, 3, -2, -1 ] ], 1.5 ] - ], - [ - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 2, -5, 0, 2, -2, 0 ], [ 4, -5, 0, 2, -2, -1 ], [ 2, -4, 0, 3, -2, -1 ] ], 0.625 ], - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 2, -5, 0, 2, -2, 0 ], [ 4, -5, 0, 2, -2, -1 ], [ 3, -4, 0, 2, -2, -1 ] ], 1.25 ] - ], - [ - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 3, -4, 0, 2, -2, -2 ], [ 4, -5, 0, 2, -2, -1 ], [ 3, -4, 0, 2, -2, -1 ] ], 0.625 ], - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 3, -4, 0, 2, -2, -2 ], [ 4, -5, 0, 2, -2, -1 ], [ 4, -5, 0, 2, -1, -2 ] ], 1.625 ] - ], - [ - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 3, -4, 0, 2, -2, -2 ], [ 4, -5, 0, 2, -2, -1 ], [ 4, -4, 0, 2, -2, -2 ] ], 1.5 ], - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 3, -4, 0, 2, -2, -2 ], [ 3, -4, 0, 2, -2, -1 ], [ 4, -4, 0, 2, -2, -2 ] ], 1.5 ] - ], - [ - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 3, -4, -1, 2, -1, -2 ], [ 3, -4, 0, 2, -2, -1 ], [ 4, -4, 0, 2, -2, -2 ] ], 1.625 ], - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 3, -4, -1, 2, -1, -2 ], [ 4, -5, 0, 2, -1, -2 ], [ 4, -4, 0, 2, -2, -2 ] ], 1.25 ], - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 3, -4, -1, 2, -1, -2 ], [ 4, -5, 0, 2, -1, -2 ], [ 4, -4, 0, 1, -1, -2 ] ], 1.75 ] - ], - [ - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 3, -4, -1, 2, -1, -2 ], [ 3, -3, 0, 2, -1, -2 ], [ 4, -4, 0, 1, -1, -2 ] ], 0.75 ], - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 3, -4, -1, 2, -1, -2 ], [ 3, -3, 0, 2, -1, -2 ], [ 3, -4, 1, 2, -1, -2 ] ], 1.5 ], - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 2, -4, 0, 3, -1, -2 ], [ 3, -3, 0, 2, -1, -2 ], [ 3, -4, 1, 2, -1, -2 ] ], 1 ] - ], - [ - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 2, -4, 0, 3, -1, -2 ], [ 2, -3, 0, 3, -1, -2 ], [ 3, -4, 1, 2, -1, -2 ] ], 1.625 ] - ], - [ - [ [ [ 1, -4, 1, 3, -1, -2 ], [ 2, -4, 0, 3, -1, -2 ], [ 2, -3, 0, 3, -1, -2 ], [ 3, -4, 1, 2, -1, -2 ] ], 1.25 ], - [ [ [ 1, -4, 1, 3, -1, -2 ], [ 2, -4, 0, 3, -1, -2 ], [ 4, -4, 1, 1, -1, -2 ], [ 3, -4, 1, 2, -1, -2 ] ], 0.5 ], - [ [ [ 1, -4, 1, 3, -1, -2 ], [ 2, -3, 1, 2, -1, -2 ], [ 4, -4, 1, 1, -1, -2 ], [ 3, -4, 1, 2, -1, -2 ] ], 1 ] - ], - [ - [ [ [ 1, -4, 1, 3, -1, -2 ], [ 2, -3, 1, 2, -1, -2 ], [ 4, -4, 1, 1, -1, -2 ], [ 2, -2, 1, 2, -1, -2 ] ], 1.5 ], - [ [ [ 1, -4, 1, 3, -1, -2 ], [ 2, -3, 1, 2, -1, -2 ], [ 3, -4, 1, 2, -1, -2 ], [ 2, -2, 1, 2, -1, -2 ] ], 1.125 ] - ], - [ - [ [ [ 1, -4, 1, 3, -1, -2 ], [ 2, -3, 1, 2, -1, -2 ], [ 3, -5, 1, 3, -1, -2 ], [ 2, -2, 1, 2, -1, -2 ] ], 1.125 ] - ], - [ - [ [ [ 1, -4, 1, 3, -1, -2 ], [ 2, -3, 1, 2, -1, -2 ], [ 1, -2, 1, 3, -1, -2 ], [ 2, -2, 1, 2, -1, -2 ] ], 1 ] - ], - [ - [ [ [ 1, -4, 1, 3, -1, -2 ], [ 2, -3, 1, 2, -1, -2 ], [ 2, -4, 2, 3, -1, -2 ], [ 2, -2, 1, 2, -1, -2 ] ], 1.25 ], - [ [ [ 1, -4, 1, 3, -1, -2 ], [ 2, -3, 1, 2, -1, -2 ], [ 2, -4, 2, 3, -1, -2 ], [ 3, -3, 0, 2, -1, -2 ] ], 0.875 ] - ], - [ - [ [ [ 1, -4, 1, 3, -1, -2 ], [ 2, -4, 1, 2, -1, -2 ], [ 2, -4, 2, 3, -1, -2 ], [ 3, -3, 0, 2, -1, -2 ] ], 0.875 ], - [ [ [ 1, -4, 1, 3, -1, -2 ], [ 2, -4, 1, 2, -1, -2 ], [ 3, -4, 1, 2, -1, -2 ], [ 3, -3, 0, 2, -1, -2 ] ], 0.5 ], - [ [ [ 1, -4, 1, 3, -1, -2 ], [ 2, -4, 1, 2, -1, -2 ], [ 3, -4, 1, 2, -1, -2 ], [ 2, -4, 2, 3, -1, -2 ] ], 1.25 ] - ], - [ - [ [ [ 1, -4, 1, 3, -1, -2 ], [ 2, -4, 1, 2, -1, -2 ], [ 3, -4, 1, 2, -1, -2 ], [ 4, -4, 1, 1, -1, -2 ] ], 0.5 ] - ], - [ - [ [ [ 1, -4, 1, 3, -1, -2 ], [ 3, -4, 1, 1, -1, -2 ], [ 3, -4, 1, 2, -1, -2 ], [ 4, -4, 1, 1, -1, -2 ] ], 1.625 ], - [ [ [ 2, -4, 1, 2, -1, -2 ], [ 3, -4, 1, 1, -1, -2 ], [ 3, -4, 1, 2, -1, -2 ], [ 4, -4, 1, 1, -1, -2 ] ], 1.25 ], - [ [ [ 2, -4, 1, 2, -1, -2 ], [ 3, -4, 1, 1, -1, -2 ], [ 3, -4, 1, 2, -1, -2 ], [ 1, -4, 1, 2, -1, -1 ] ], 0.625 ] - ], - [ - [ [ [ 2, -4, 1, 2, -1, -2 ], [ 3, -4, 1, 1, -1, -2 ], [ 3, -4, 1, 2, -1, -2 ], [ 3, -4, 0, 1, -1, -2 ] ], 1 ] - ], - [ - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 3, -4, 1, 1, -1, -2 ], [ 3, -4, 1, 2, -1, -2 ], [ 3, -4, 0, 1, -1, -2 ] ], 1.125 ] - ], - [ - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 3, -4, 1, 1, -1, -2 ], [ 4, -4, 1, 1, -1, -2 ], [ 3, -4, 0, 1, -1, -2 ] ], 1 ] - ], - [ - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 3, -4, 1, 1, -1, -2 ], [ 4, -4, 1, 1, -1, -2 ], [ 2, -4, 1, 2, -1, -2 ] ], 1.625 ], - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 2, -3, 0, 2, -1, -2 ], [ 4, -4, 1, 1, -1, -2 ], [ 2, -4, 1, 2, -1, -2 ] ], 1.625 ], - [ [ [ 2, -4, 0, 2, -1, -2 ], [ 2, -3, 0, 2, -1, -2 ], [ 3, -3, 0, 2, -1, -2 ], [ 2, -4, 1, 2, -1, -2 ] ], 1.375 ] - ], - [ - [ [ [ 1, -2, 0, 2, -1, -2 ], [ 2, -3, 0, 2, -1, -2 ], [ 3, -3, 0, 2, -1, -2 ], [ 2, -4, 1, 2, -1, -2 ] ], 0.625 ], - [ [ [ 1, -2, 0, 2, -1, -2 ], [ 2, -3, 0, 2, -1, -2 ], [ 2, -3, 0, 2, -1, -1 ], [ 2, -4, 1, 2, -1, -2 ] ], 1.375 ] - ], - [ - [ [ [ 1, -2, 0, 2, -1, -2 ], [ 2, -3, 0, 2, -1, -2 ], [ 2, -3, 0, 2, -1, -1 ], [ 2, -2, 0, 2, -1, -3 ] ], 1.375 ], - [ [ [ 1, -2, 0, 2, -1, -2 ], [ 1, -1, 0, 2, -1, -2 ], [ 2, -3, 0, 2, -1, -1 ], [ 2, -2, 0, 2, -1, -3 ] ], 1.375 ] - ], - [ - [ [ [ 0, 0, 0, 2, -1, -2 ], [ 1, -1, 0, 2, -1, -2 ], [ 2, -3, 0, 2, -1, -1 ], [ 2, -2, 0, 2, -1, -3 ] ], 1.25 ], - [ [ [ 0, 0, 0, 2, -1, -2 ], [ 1, -1, 0, 2, -1, -2 ], [ 2, -1, -1, 2, -1, -2 ], [ 2, -2, 0, 2, -1, -3 ] ], 1 ] - ], - [ - [ [ [ 2, -2, -1, 2, -1, -3 ], [ 1, -1, 0, 2, -1, -2 ], [ 2, -1, -1, 2, -1, -2 ], [ 2, -2, 0, 2, -1, -3 ] ], 1.75 ], - [ [ [ 2, -2, -1, 2, -1, -3 ], [ 2, -2, -1, 2, -1, -2 ], [ 2, -1, -1, 2, -1, -2 ], [ 2, -2, 0, 2, -1, -3 ] ], 0.625 ] - ], - [ - [ [ [ 2, -2, -1, 2, -1, -3 ], [ 2, -2, -1, 2, -1, -2 ], [ 2, -1, -1, 2, -1, -2 ], [ 1, -1, -2, 2, -1, -2 ] ], 0.5 ], - [ [ [ 2, -3, -1, 2, -1, -2 ], [ 2, -2, -1, 2, -1, -2 ], [ 2, -1, -1, 2, -1, -2 ], [ 1, -1, -2, 2, -1, -2 ] ], 0.875 ] - ], - [ - [ [ [ 2, -3, -1, 2, -1, -2 ], [ 2, -2, -1, 2, -1, -2 ], [ 3, -2, -2, 2, -1, -2 ], [ 1, -1, -2, 2, -1, -2 ] ], 0.875 ] - ], - [ - [ [ [ 2, -3, -1, 2, -1, -2 ], [ 2, -2, -1, 2, -1, -2 ], [ 3, -2, -2, 2, -1, -2 ], [ 2, -2, -3, 2, -1, -2 ] ], 1.125 ], - [ [ [ 2, -3, -2, 2, -1, -2 ], [ 2, -2, -1, 2, -1, -2 ], [ 3, -2, -2, 2, -1, -2 ], [ 2, -2, -3, 2, -1, -2 ] ], 0.5 ] - ], - [ - [ [ [ 2, -3, -2, 2, -1, -2 ], [ 2, -2, -1, 2, -1, -2 ], [ 2, -2, -1, 3, -1, -2 ], [ 2, -2, -3, 2, -1, -2 ] ], 0.875 ], - [ [ [ 2, -3, -2, 2, -1, -2 ], [ 2, -2, -1, 2, -1, -2 ], [ 2, -2, -1, 3, -1, -2 ], [ 2, -2, -1, 2, -2, -2 ] ], 0.875 ], - [ [ [ 2, -2, -1, 1, -1, -2 ], [ 2, -2, -1, 2, -1, -2 ], [ 2, -2, -1, 3, -1, -2 ], [ 2, -2, -1, 2, -2, -2 ] ], 1.375 ] - ], - [ - [ [ [ 2, -2, -1, 2, -1, -3 ], [ 2, -2, -1, 2, -1, -2 ], [ 2, -2, -1, 3, -1, -2 ], [ 2, -2, -1, 2, -2, -2 ] ], 0.875 ] - ], - [ - [ [ [ 2, -2, -1, 2, -1, -3 ], [ 2, -1, -1, 2, -2, -2 ], [ 2, -2, -1, 3, -1, -2 ], [ 2, -2, -1, 2, -2, -2 ] ], 0.875 ] - ], - [ - [ [ [ 2, -2, -1, 2, -1, -3 ], [ 2, -1, -1, 2, -2, -2 ], [ 3, -2, -1, 2, -2, -2 ], [ 2, -2, -1, 2, -2, -2 ] ], 1.75 ] - ], - [ - [ [ [ 2, -2, -1, 2, -1, -3 ], [ 2, -1, -1, 2, -2, -2 ], [ 4, -2, -1, 1, -2, -2 ], [ 2, -2, -1, 2, -2, -2 ] ], 0.875 ], - [ [ [ 2, -2, -1, 2, -1, -3 ], [ 1, -2, -1, 2, -2, -1 ], [ 4, -2, -1, 1, -2, -2 ], [ 2, -2, -1, 2, -2, -2 ] ], 1.5 ] - ], - [ - [ [ [ 2, -2, -1, 2, -1, -3 ], [ 1, -2, -1, 2, -2, -1 ], [ 4, -2, -1, 1, -2, -2 ], [ 1, -2, -1, 2, -1, -1 ] ], 1.625 ], - [ [ [ 2, -2, -1, 1, -2, -1 ], [ 1, -2, -1, 2, -2, -1 ], [ 4, -2, -1, 1, -2, -2 ], [ 1, -2, -1, 2, -1, -1 ] ], 0.625 ], - [ [ [ 2, -2, -1, 1, -2, -1 ], [ 1, -2, -1, 2, -2, -1 ], [ 3, -2, -1, 1, -2, -1 ], [ 1, -2, -1, 2, -1, -1 ] ], 0.875 ] - ], - [ - [ [ [ 2, -2, -1, 1, -2, -1 ], [ 1, -2, -1, 2, -2, -1 ], [ 4, -2, -1, 0, -2, -1 ], [ 1, -2, -1, 2, -1, -1 ] ], 0.625 ], - [ [ [ 2, -2, -1, 1, -2, -1 ], [ 1, -2, -1, 2, -2, -1 ], [ 4, -2, -1, 0, -2, -1 ], [ 3, -3, -1, 1, -2, -1 ] ], 1.75 ], - [ [ [ 2, -2, -1, 1, -2, -1 ], [ 1, -2, -1, 1, -2, 0 ], [ 4, -2, -1, 0, -2, -1 ], [ 3, -3, -1, 1, -2, -1 ] ], 1.25 ] - ], - [ - [ [ [ 2, -2, -1, 1, -2, -1 ], [ 1, -2, -1, 1, -2, 0 ], [ 4, -2, -1, 0, -2, -1 ], [ 3, -2, 0, 0, -2, -1 ] ], 1.375 ] - ], - [ - [ [ [ 2, -2, -1, 0, -2, 0 ], [ 1, -2, -1, 1, -2, 0 ], [ 4, -2, -1, 0, -2, -1 ], [ 3, -2, 0, 0, -2, -1 ] ], 1.875 ], - [ [ [ 2, -2, -1, 0, -2, 0 ], [ 1, -2, -1, 1, -2, 0 ], [ 4, -2, -1, 0, -2, -1 ], [ 2, -2, -1, 1, -2, 0 ] ], 0.5 ], - [ [ [ 2, -2, -1, 0, -2, 0 ], [ 1, -2, -1, 1, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 2, -2, -1, 1, -2, 0 ] ], 0.875 ] - ], - [ - [ [ [ 2, -2, -1, 0, -2, 0 ], [ 0, 0, -1, 1, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 2, -2, -1, 1, -2, 0 ] ], 1.625 ], - [ [ [ 1, -1, -2, 1, -2, 0 ], [ 0, 0, -1, 1, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 2, -2, -1, 1, -2, 0 ] ], 1.625 ] - ], - [ - [ [ [ 1, -1, -2, 1, -2, 0 ], [ 1, -2, 0, 1, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 2, -2, -1, 1, -2, 0 ] ], 1.5 ] - ], - [ - [ [ [ 1, -1, -2, 1, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 2, -2, -1, 1, -2, 0 ] ], 0.375 ], - [ [ [ 1, -1, -2, 1, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 1, 0, -1, 1, -2, 0 ] ], 1.375 ], - [ [ [ 1, -2, -1, 1, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 1, 0, -1, 1, -2, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 0, -1, 1, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 1, 0, -1, 1, -2, 0 ] ], 0.5 ] - ], - [ - [ [ [ 0, 0, -1, 1, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ], [ 1, -1, -1, 2, -2, 0 ], [ 1, 0, -1, 1, -2, 0 ] ], 1.125 ] - ], - [ - [ [ [ 0, 0, -1, 1, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 1, 0, -1, 1, -2, 0 ] ], 0.875 ], - [ [ [ -1, 0, -1, 2, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 1, 0, -1, 1, -2, 0 ] ], 1 ], - [ [ [ -1, 0, -1, 2, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 1, -1, -1, 2, -2, 0 ] ], 1.125 ] - ], - [ - [ [ [ -1, 0, -1, 2, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 0, -1, -1, 3, -2, 0 ] ], 0.875 ], - [ [ [ 0, -1, -2, 2, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 0, -1, -1, 3, -2, 0 ] ], 1.625 ] - ], - [ - [ [ [ 1, -1, -2, 1, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 0, -1, -1, 3, -2, 0 ] ], 0.5 ] - ], - [ - [ [ [ 1, -1, -2, 1, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ], [ 1, -1, -1, 2, -2, 0 ], [ 0, -1, -1, 3, -2, 0 ] ], 0.5 ], - [ [ [ 1, -1, -2, 1, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ], [ 1, -1, -1, 2, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ] ], 0.75 ], - [ [ [ -1, -1, -1, 2, -2, 1 ], [ 0, -1, -1, 2, -2, 0 ], [ 1, -1, -1, 2, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ] ], 0.5 ] - ], - [ - [ [ [ -1, -1, -1, 2, -2, 1 ], [ 0, -1, -1, 2, -2, 0 ], [ 1, -1, -1, 1, -2, 1 ], [ 2, -1, -1, 1, -2, 0 ] ], 1.75 ], - [ [ [ -1, -1, -1, 2, -2, 1 ], [ 1, -1, -1, 1, -2, 0 ], [ 1, -1, -1, 1, -2, 1 ], [ 2, -1, -1, 1, -2, 0 ] ], 0.875 ], - [ [ [ 0, 0, -1, 1, -2, 0 ], [ 1, -1, -1, 1, -2, 0 ], [ 1, -1, -1, 1, -2, 1 ], [ 2, -1, -1, 1, -2, 0 ] ], 0.5 ] - ], - [ - [ [ [ 0, 0, -1, 1, -2, 0 ], [ 1, -1, -1, 1, -2, 0 ], [ 1, -1, -1, 1, -2, 1 ], [ 0, -1, -1, 2, -2, 0 ] ], 1.375 ], - [ [ [ 0, -1, -1, 1, -2, 1 ], [ 1, -1, -1, 1, -2, 0 ], [ 1, -1, -1, 1, -2, 1 ], [ 0, -1, -1, 2, -2, 0 ] ], 1.25 ] - ], - [ - [ [ [ 1, -2, -1, 1, -2, 0 ], [ 1, -1, -1, 1, -2, 0 ], [ 1, -1, -1, 1, -2, 1 ], [ 0, -1, -1, 2, -2, 0 ] ], 1.625 ] - ], - [ - [ [ [ 1, -2, -1, 1, -2, 0 ], [ 1, -1, -1, 1, -2, 0 ], [ 1, -1, -1, 2, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ] ], 0.75 ] - ], - [ - [ [ [ 1, -2, -1, 1, -2, 0 ], [ 1, -1, -1, 1, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ] ], 1.5 ], - [ [ [ 1, -1, -1, 1, -3, 0 ], [ 1, -1, -1, 1, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ] ], 0.5 ] - ], - [ - [ [ [ 1, -1, -1, 1, -3, 0 ], [ 1, -1, -1, 1, -2, 0 ], [ 2, -1, -2, 1, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ] ], 1.625 ], - [ [ [ 1, -1, -2, 1, -2, 0 ], [ 1, -1, -1, 1, -2, 0 ], [ 2, -1, -2, 1, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ] ], 1.625 ] - ], - [ - [ [ [ 1, -1, -2, 1, -2, 0 ], [ 1, -1, -1, 1, -2, 0 ], [ 1, -1, -1, 2, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ] ], 1.375 ], - [ [ [ -1, -1, -1, 3, -2, 0 ], [ 1, -1, -1, 1, -2, 0 ], [ 1, -1, -1, 2, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ] ], 1.375 ] - ], - [ - [ [ [ -1, -1, -1, 3, -2, 0 ], [ 1, -2, -1, 2, -2, 0 ], [ 1, -1, -1, 2, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ] ], 1.625 ], - [ [ [ -1, -1, -1, 3, -2, 0 ], [ 1, -2, -1, 2, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ] ], 1.25 ], - [ [ [ -1, -2, -1, 2, -2, 0 ], [ 1, -2, -1, 2, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ] ], 1.75 ] - ], - [ - [ [ [ 0, -2, -1, 1, -2, 0 ], [ 1, -2, -1, 2, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ] ], 1.5 ], - [ [ [ 0, -2, -1, 1, -2, 0 ], [ 1, -2, -1, 2, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 1, -1, -1, 1, -2, 0 ] ], 0.5 ], - [ [ [ 0, -2, -1, 1, -2, 0 ], [ 2, -2, -1, 1, -2, 0 ], [ 2, -1, -1, 1, -2, 0 ], [ 1, -1, -1, 1, -2, 0 ] ], 0.5 ] - ], - [ - [ [ [ 0, -2, -1, 1, -2, 0 ], [ 2, -2, -1, 1, -2, 0 ], [ 1, -2, -1, 1, -2, 0 ], [ 1, -1, -1, 1, -2, 0 ] ], 0.875 ], - [ [ [ 1, -2, -1, 0, -2, 0 ], [ 2, -2, -1, 1, -2, 0 ], [ 1, -2, -1, 1, -2, 0 ], [ 1, -1, -1, 1, -2, 0 ] ], 1.625 ] - ], - [ - [ [ [ 0, -2, -2, 1, -2, 0 ], [ 2, -2, -1, 1, -2, 0 ], [ 1, -2, -1, 1, -2, 0 ], [ 1, -1, -1, 1, -2, 0 ] ], 1.375 ], - [ [ [ 0, -2, -2, 1, -2, 0 ], [ 2, -2, -1, 1, -2, 0 ], [ 2, -2, -1, 0, -2, 0 ], [ 1, -1, -1, 1, -2, 0 ] ], 1.75 ], - [ [ [ 0, -2, -2, 1, -2, 0 ], [ 2, -2, -1, 1, -2, 0 ], [ 2, -2, -1, 0, -2, 0 ], [ 2, -2, -2, 1, -2, 0 ] ], 1.5 ] - ], - [ - [ [ [ 0, -2, -2, 1, -2, 0 ], [ 2, -2, -1, 1, -2, 0 ], [ 1, -1, -2, 1, -2, 0 ], [ 2, -2, -2, 1, -2, 0 ] ], 1.5 ], - [ [ [ 0, -2, -2, 1, -2, 0 ], [ 2, -2, -1, 1, -2, 0 ], [ 1, -1, -2, 1, -2, 0 ], [ 3, -2, -2, 0, -2, 0 ] ], 0.5 ] - ], - [ - [ [ [ 0, -2, -2, 1, -2, 0 ], [ 2, -2, -1, 1, -2, 0 ], [ 1, -1, -2, 1, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ] ], 1.625 ] - ], - [ - [ [ [ -1, 0, -2, 1, -2, 0 ], [ 2, -2, -1, 1, -2, 0 ], [ 1, -1, -2, 1, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ] ], 1 ], - [ [ [ -1, 0, -2, 1, -2, 0 ], [ 2, -2, -1, 1, -2, 0 ], [ 1, -1, -2, 1, -2, 0 ], [ 2, -1, -2, 1, -2, 0 ] ], 1.75 ], - [ [ [ -1, 0, -2, 1, -2, 0 ], [ 1, 0, -2, 1, -2, 0 ], [ 1, -1, -2, 1, -2, 0 ], [ 2, -1, -2, 1, -2, 0 ] ], 1.75 ] - ], - [ - [ [ [ -1, 0, -2, 1, -2, 0 ], [ 1, 0, -2, 1, -2, 0 ], [ 0, 1, -2, 1, -2, 0 ], [ 2, -1, -2, 1, -2, 0 ] ], 0.875 ] - ], - [ - [ [ [ -1, 0, -2, 1, -2, 0 ], [ 0, 2, -2, 1, -2, 0 ], [ 0, 1, -2, 1, -2, 0 ], [ 2, -1, -2, 1, -2, 0 ] ], 0.75 ], - [ [ [ -2, 2, -2, 1, -2, 0 ], [ 0, 2, -2, 1, -2, 0 ], [ 0, 1, -2, 1, -2, 0 ], [ 2, -1, -2, 1, -2, 0 ] ], 0.5 ], - [ [ [ -2, 2, -2, 1, -2, 0 ], [ 0, 2, -2, 1, -2, 0 ], [ 0, 1, -2, 1, -2, 0 ], [ 1, 1, -2, 1, -2, 0 ] ], 0.875 ] - ], - [ - [ [ [ -2, 2, -2, 1, -2, 0 ], [ 0, 2, -2, 1, -2, 0 ], [ -1, 3, -2, 1, -2, 0 ], [ 1, 1, -2, 1, -2, 0 ] ], 1.375 ], - [ [ [ -1, 1, -3, 1, -2, 0 ], [ 0, 2, -2, 1, -2, 0 ], [ -1, 3, -2, 1, -2, 0 ], [ 1, 1, -2, 1, -2, 0 ] ], 1.375 ] - ], - [ - [ [ [ -1, 1, -3, 1, -2, 0 ], [ 0, 2, -2, 1, -2, 0 ], [ -1, 3, -2, 1, -2, 0 ], [ 0, 3, -2, 1, -2, 0 ] ], 1.875 ], - [ [ [ -1, 1, -3, 1, -2, 0 ], [ 0, 2, -2, 1, -2, 0 ], [ 0, 2, -3, 1, -2, 0 ], [ 0, 3, -2, 1, -2, 0 ] ], 1.5 ] - ], - [ - [ [ [ -1, 1, -3, 1, -2, 0 ], [ 1, 1, -3, 1, -2, 0 ], [ 0, 2, -3, 1, -2, 0 ], [ 0, 3, -2, 1, -2, 0 ] ], 0.875 ] - ], - [ - [ [ [ -2, 3, -3, 1, -2, 0 ], [ 1, 1, -3, 1, -2, 0 ], [ 0, 2, -3, 1, -2, 0 ], [ 0, 3, -2, 1, -2, 0 ] ], 1.25 ], - [ [ [ -2, 3, -3, 1, -2, 0 ], [ 1, 1, -3, 1, -2, 0 ], [ 0, 2, -3, 1, -2, 0 ], [ 0, 3, -3, 1, -2, 0 ] ], 1.625 ] - ], - [ - [ [ [ -1, 2, -4, 1, -2, 0 ], [ 1, 1, -3, 1, -2, 0 ], [ 0, 2, -3, 1, -2, 0 ], [ 0, 3, -3, 1, -2, 0 ] ], 0.5 ] - ], - [ - [ [ [ -1, 2, -4, 1, -2, 0 ], [ 1, 1, -3, 1, -2, 0 ], [ 0, 2, -3, 1, -2, 0 ], [ 1, 2, -4, 1, -2, 0 ] ], 1.25 ], - [ [ [ 0, 0, -3, 1, -2, 0 ], [ 1, 1, -3, 1, -2, 0 ], [ 0, 2, -3, 1, -2, 0 ], [ 1, 2, -4, 1, -2, 0 ] ], 1.25 ] - ], - [ - [ [ [ -1, 2, -3, 1, -2, 0 ], [ 1, 1, -3, 1, -2, 0 ], [ 0, 2, -3, 1, -2, 0 ], [ 1, 2, -4, 1, -2, 0 ] ], 0.75 ], - [ [ [ -1, 2, -3, 1, -2, 0 ], [ 1, 1, -3, 1, -2, 0 ], [ 0, 2, -3, 1, -2, 0 ], [ 2, 0, -3, 1, -2, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 2, -3, 1, -2, 0 ], [ 1, 0, -3, 1, -2, 0 ], [ 0, 2, -3, 1, -2, 0 ], [ 2, 0, -3, 1, -2, 0 ] ], 0.75 ], - [ [ [ -1, 2, -3, 1, -2, 0 ], [ 1, 0, -3, 1, -2, 0 ], [ 1, 0, -2, 1, -2, 0 ], [ 2, 0, -3, 1, -2, 0 ] ], 1 ], - [ [ [ 0, 0, -2, 1, -2, 0 ], [ 1, 0, -3, 1, -2, 0 ], [ 1, 0, -2, 1, -2, 0 ], [ 2, 0, -3, 1, -2, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 0, -2, 1, -2, 0 ], [ 1, 0, -3, 1, -2, 0 ], [ 1, 0, -2, 1, -2, 0 ], [ 1, -1, -2, 1, -2, 0 ] ], 0.5 ], - [ [ [ 0, 0, -2, 1, -2, 0 ], [ 0, 0, -2, 2, -2, 0 ], [ 1, 0, -2, 1, -2, 0 ], [ 1, -1, -2, 1, -2, 0 ] ], 0.75 ], - [ [ [ 0, 0, -2, 1, -2, 0 ], [ 0, 0, -2, 2, -2, 0 ], [ 0, 1, -2, 1, -2, 0 ], [ 1, -1, -2, 1, -2, 0 ] ], 0.625 ] - ], - [ - [ [ [ 0, 0, -2, 1, -2, 0 ], [ 0, 0, -2, 2, -2, 0 ], [ 1, 0, -3, 1, -2, 0 ], [ 1, -1, -2, 1, -2, 0 ] ], 0.75 ] - ], - [ - [ [ [ 0, -1, -2, 2, -2, 0 ], [ 0, 0, -2, 2, -2, 0 ], [ 1, 0, -3, 1, -2, 0 ], [ 1, -1, -2, 1, -2, 0 ] ], 0.625 ], - [ [ [ 0, -1, -2, 2, -2, 0 ], [ 1, 0, -2, 1, -2, 0 ], [ 1, 0, -3, 1, -2, 0 ], [ 1, -1, -2, 1, -2, 0 ] ], 0.875 ] - ], - [ - [ [ [ 0, -1, -2, 2, -2, 0 ], [ 1, 0, -2, 1, -2, 0 ], [ 1, 0, -3, 1, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ] ], 1.625 ], - [ [ [ 0, -1, -2, 2, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ], [ 1, 0, -3, 1, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ] ], 0.75 ], - [ [ [ 0, -1, -2, 2, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ], [ 0, 0, -2, 2, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ] ], 1.375 ] - ], - [ - [ [ [ 0, -1, -2, 2, -2, 0 ], [ 1, 0, -2, 2, -3, 0 ], [ 0, 0, -2, 2, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ] ], 1.25 ] - ], - [ - [ [ [ 0, -1, -2, 2, -2, 0 ], [ 1, -1, -1, 2, -2, 0 ], [ 0, 0, -2, 2, -2, 0 ], [ 0, -1, -1, 2, -2, 0 ] ], 1.25 ], - [ [ [ 0, -1, -2, 2, -2, 0 ], [ 1, -1, -1, 2, -2, 0 ], [ 0, 0, -2, 2, -2, 0 ], [ 1, -2, -2, 2, -2, 0 ] ], 0.875 ] - ], - [ - [ [ [ 0, -1, -2, 2, -2, 0 ], [ 1, -1, -1, 2, -2, 0 ], [ 0, 0, -2, 2, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ] ], 1.375 ], - [ [ [ 0, -1, -2, 2, -2, 0 ], [ 1, -1, -1, 2, -2, 0 ], [ 1, -1, -3, 2, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ] ], 0.625 ], - [ [ [ 0, -1, -2, 2, -2, 0 ], [ 2, -2, -2, 2, -2, 0 ], [ 1, -1, -3, 2, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ] ], 1 ] - ], - [ - [ [ [ 1, -2, -3, 2, -2, 0 ], [ 2, -2, -2, 2, -2, 0 ], [ 1, -1, -3, 2, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ] ], 0.875 ], - [ [ [ 1, -2, -3, 2, -2, 0 ], [ 2, -2, -2, 2, -2, 0 ], [ 1, -2, -2, 2, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ] ], 0.75 ] - ], - [ - [ [ [ 1, -2, -3, 2, -2, 0 ], [ 2, -1, -2, 2, -3, 0 ], [ 1, -2, -2, 2, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ] ], 1.125 ], - [ [ [ 1, -2, -3, 2, -2, 0 ], [ 2, -1, -2, 2, -3, 0 ], [ 0, 0, -2, 2, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ] ], 1.5 ], - [ [ [ 1, -1, -2, 1, -2, 0 ], [ 2, -1, -2, 2, -3, 0 ], [ 0, 0, -2, 2, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ] ], 1.625 ], - [ [ [ 1, -1, -2, 1, -2, 0 ], [ "Rest" ], [ 0, 0, -2, 2, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ] ], 1.625 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, -2, 2, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ] ], 1.25 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, -2, 2, -2, 0 ], [ "Rest" ] ], 1.25 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 7.25 ] - ] - ] -], -"last_changes": -[ - [ [ 1, -2, -3, 2, -2, 0 ], [ 2, -2, -2, 2, -2, 0 ], [ 1, -1, -3, 2, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ] ], - [ [ 1, -2, -3, 2, -2, 0 ], [ 2, -2, -2, 2, -2, 0 ], [ 1, -2, -2, 2, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ] ], - [ [ 1, -2, -3, 2, -2, 0 ], [ 2, -1, -2, 2, -3, 0 ], [ 1, -2, -2, 2, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ] ], - [ [ 1, -2, -3, 2, -2, 0 ], [ 2, -1, -2, 2, -3, 0 ], [ 0, 0, -2, 2, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ] ], - [ [ 1, -1, -2, 1, -2, 0 ], [ 2, -1, -2, 2, -3, 0 ], [ 0, 0, -2, 2, -2, 0 ], [ 1, -1, -2, 2, -2, 0 ] ] -], -"cur_uid": "55bd25a1", -"ref_uid": "6a9928d6", -"order_seed": 807265, -"dur_seed": 754968, -"motifs_seed": 848720, -"entrances_probs_vals": [ 0, 0, 0, 0.41, 1.84, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 0.41, 1.84, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 0.41, 1.84, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2430, -293 ], [ -869, 1211 ], [ -832, 1285 ], [ -702, 1211 ] ], -"step_probs_vals": [ -1200, 1200, 0.0020576131687243, 0.068181818181818, 0.074074074074074, 0.0625, 0.20576131687243, 0.0625, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61316872427983, 0, 0.98971193415638, 0 ], -"passages_weights": [ 0.48, 0.46, 0.48, 1, 1 ], -"hd_exp": 9, -"hd_invert": 0, -"order": -[ - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 3, 0 ], [ 1, 2 ], [ ] ], - [ [ 3, 2 ], [ 0, 1 ], [ ] ], - [ [ 1 ], [ 2, 0, 3 ], [ ] ], - [ [ 3 ], [ 0, 1, 2 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 3 ], [ 0, 1, 2 ], [ ] ], - [ [ 3 ], [ 0, 1, 2 ], [ ] ], - [ [ 2, 0 ], [ 3, 1 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 3 ], [ 1, 0, 2 ], [ ] ], - [ [ 2 ], [ 0, 3, 1 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 2, 1 ], [ 0, 3 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 2 ], [ 3, 0, 1 ], [ ] ], - [ [ 3 ], [ 0, 1, 2 ], [ ] ], - [ [ 2 ], [ 3, 1, 0 ], [ ] ], - [ [ 0, 1 ], [ 2, 3 ], [ ] ], - [ [ 3, 1 ], [ 2, 0 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 3, 2 ], [ 0, 1 ], [ ] ], - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 1, 0 ], [ 2, 3 ], [ ] ], - [ [ 2, 0 ], [ 1, 3 ], [ ] ], - [ [ 0, 2 ], [ 1, 3 ], [ ] ], - [ [ 0, 1 ], [ 3, 2 ], [ ] ], - [ [ 0 ], [ 1, 2, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 3 ], [ 0, 2, 1 ], [ ] ], - [ [ 1, 0 ], [ 3, 2 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 0, 1 ], [ 2, 3 ], [ ] ], - [ [ 0 ], [ 1, 2, 3 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 0, 2 ], [ 3, 1 ], [ ] ], - [ [ 1, 3 ], [ 0, 2 ], [ ] ], - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 1 ], [ 2, 3, 0 ], [ ] ], - [ [ 1, 3, 2 ], [ 0 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 3, 0 ], [ 2, 1 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 1 ], [ 0, 3, 2 ], [ ] ], - [ [ 2, 3 ], [ 1, 0 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 2 ], [ 1, 3, 0 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 1 ], [ 2, 0, 3 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 1 ], [ 2, 3, 0 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 1, 3 ], [ 2, 0 ], [ ] ], - [ [ 3, 1 ], [ 2, 0 ], [ ] ], - [ [ 1, 3 ], [ 2, 0 ], [ ] ], - [ [ 3 ], [ 1, 2, 0 ], [ ] ], - [ [ 2 ], [ 0, 3, 1 ], [ ] ], - [ [ 1, 3 ], [ 2, 0 ], [ ] ], - [ [ 1 ], [ 0, 2, 3 ], [ ] ], - [ [ 1, 0 ], [ 2, 3 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 2 ], [ 0, 3, 1 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 1, 3 ], [ 2, 0 ], [ ] ], - [ [ 1, 0 ], [ 3, 2 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 1, 2 ], [ 0, 3 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 2, 1 ], [ 0, 3 ], [ ] ], - [ [ 3 ], [ 1, 2, 0 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 3, 2 ], [ 0, 1 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 2, 0 ], [ 1, 3 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 3 ], [ 1, 2, 0 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 100, 100 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/55f9b81e/55f9b81e_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3/55f9b81e/55f9b81e_code.scd deleted file mode 100644 index 2dad11e..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/55f9b81e/55f9b81e_code.scd +++ /dev/null @@ -1,958 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - if(pDistance < 0, {stepFunc.value(abs(pDistance))}, {0.001}); - //stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/55f9b81e/55f9b81e_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3/55f9b81e/55f9b81e_mus_model.json deleted file mode 100644 index 52fe7d6..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/55f9b81e/55f9b81e_mus_model.json +++ /dev/null @@ -1,443 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ -3, 1, 1, 4, 1, -2 ], [ "Rest" ] ], 1.125 ], - [ [ [ -2, 0, 0, 3, 1, -2 ], [ "Rest" ], [ -3, 1, 1, 4, 1, -2 ], [ "Rest" ] ], 1.75 ], - [ [ [ -2, 0, 0, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -3, 1, 1, 4, 1, -2 ], [ "Rest" ] ], 1.375 ], - [ [ [ -2, 0, 0, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -3, 1, 1, 4, 1, -2 ], [ -2, 1, 1, 4, 1, -2 ] ], 1 ] - ], - [ - [ [ [ -2, 0, 0, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -2, 0, 0, 4, 1, -2 ], [ -2, 1, 1, 4, 1, -2 ] ], 1.5 ] - ], - [ - [ [ [ -2, 0, 0, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -1, 0, 0, 3, 1, -2 ], [ -2, 1, 1, 4, 1, -2 ] ], 0.875 ] - ], - [ - [ [ [ -2, 0, 0, 3, 1, -2 ], [ -3, 1, 2, 4, 1, -2 ], [ -1, 0, 0, 3, 1, -2 ], [ -2, 1, 1, 4, 1, -2 ] ], 1.125 ] - ], - [ - [ [ [ -4, 1, 2, 4, 1, -2 ], [ -3, 1, 2, 4, 1, -2 ], [ -1, 0, 0, 3, 1, -2 ], [ -2, 1, 1, 4, 1, -2 ] ], 0.75 ] - ], - [ - [ [ [ -4, 1, 1, 4, 2, -2 ], [ -3, 1, 2, 4, 1, -2 ], [ -1, 0, 0, 3, 1, -2 ], [ -2, 1, 1, 4, 1, -2 ] ], 1.25 ] - ], - [ - [ [ [ -4, 1, 1, 4, 2, -2 ], [ -2, 0, 1, 4, 1, -2 ], [ -1, 0, 0, 3, 1, -2 ], [ -2, 1, 1, 4, 1, -2 ] ], 1.125 ] - ], - [ - [ [ [ -4, 1, 1, 4, 2, -2 ], [ -2, 0, 1, 4, 1, -2 ], [ -3, 1, 2, 4, 1, -2 ], [ -2, 1, 1, 4, 1, -2 ] ], 1 ] - ], - [ - [ [ [ -4, 2, 1, 4, 1, -2 ], [ -2, 0, 1, 4, 1, -2 ], [ -3, 1, 2, 4, 1, -2 ], [ -2, 1, 1, 4, 1, -2 ] ], 1.75 ] - ], - [ - [ [ [ -4, 2, 1, 4, 1, -2 ], [ -2, 1, 2, 3, 1, -2 ], [ -3, 1, 2, 4, 1, -2 ], [ -2, 1, 1, 4, 1, -2 ] ], 1.75 ] - ], - [ - [ [ [ -4, 2, 1, 4, 1, -2 ], [ -2, 1, 2, 3, 1, -2 ], [ -2, 0, 1, 4, 1, -2 ], [ -2, 1, 1, 4, 1, -2 ] ], 1.25 ] - ], - [ - [ [ [ -4, 2, 1, 4, 1, -2 ], [ -2, 1, 2, 3, 1, -2 ], [ -2, 1, 1, 4, 0, -2 ], [ -2, 1, 1, 4, 1, -2 ] ], 0.875 ] - ], - [ - [ [ [ -2, 1, 1, 3, 0, -2 ], [ -2, 1, 2, 3, 1, -2 ], [ -2, 1, 1, 4, 0, -2 ], [ -2, 1, 1, 4, 1, -2 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 1, 3, 0, -2 ], [ -2, 1, 2, 3, 1, -2 ], [ -3, 2, 2, 3, 1, -2 ], [ -2, 1, 1, 4, 1, -2 ] ], 1.625 ] - ], - [ - [ [ [ -2, 1, 1, 3, 0, -2 ], [ -2, 2, 2, 3, 0, -2 ], [ -3, 2, 2, 3, 1, -2 ], [ -2, 1, 1, 4, 1, -2 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 1, 3, 0, -2 ], [ -2, 2, 2, 3, 0, -2 ], [ -3, 3, 2, 3, 0, -2 ], [ -2, 1, 1, 4, 1, -2 ] ], 1.75 ] - ], - [ - [ [ [ -2, 1, 1, 3, 0, -2 ], [ -2, 2, 2, 3, 0, -2 ], [ -3, 3, 2, 3, 0, -2 ], [ -2, 2, 2, 3, 1, -2 ] ], 1.25 ] - ], - [ - [ [ [ -2, 1, 1, 3, 0, -2 ], [ -2, 2, 2, 3, 0, -2 ], [ -2, 1, 1, 3, 0, -1 ], [ -2, 2, 2, 3, 1, -2 ] ], 1.625 ] - ], - [ - [ [ [ -2, 0, 1, 3, 0, -1 ], [ -2, 2, 2, 3, 0, -2 ], [ -2, 1, 1, 3, 0, -1 ], [ -2, 2, 2, 3, 1, -2 ] ], 1.375 ] - ], - [ - [ [ [ -2, 0, 1, 3, 0, -1 ], [ -2, 2, 2, 3, 0, -2 ], [ -1, 0, 0, 3, 0, -1 ], [ -2, 2, 2, 3, 1, -2 ] ], 1.75 ] - ], - [ - [ [ [ -2, 0, 1, 3, 0, -1 ], [ -2, 2, 2, 3, 0, -2 ], [ -2, 0, 1, 3, 0, 0 ], [ -2, 2, 2, 3, 1, -2 ] ], 1 ] - ], - [ - [ [ [ -2, 0, 1, 3, 0, -1 ], [ -2, 2, 2, 3, 0, -2 ], [ -2, 0, 1, 3, 0, 0 ], [ -1, 2, 2, 3, -1, -2 ] ], 1.375 ] - ], - [ - [ [ [ -2, -1, 1, 3, 0, 0 ], [ -2, 2, 2, 3, 0, -2 ], [ -2, 0, 1, 3, 0, 0 ], [ -1, 2, 2, 3, -1, -2 ] ], 1.375 ] - ], - [ - [ [ [ -2, -1, 1, 3, 0, 0 ], [ -1, 0, 1, 2, 0, 0 ], [ -2, 0, 1, 3, 0, 0 ], [ -1, 2, 2, 3, -1, -2 ] ], 1.625 ] - ], - [ - [ [ [ -2, -1, 1, 3, 0, 0 ], [ -1, 0, 1, 2, 0, 0 ], [ -2, 0, 1, 3, 0, 0 ], [ -2, 0, 1, 3, 0, 1 ] ], 1.25 ] - ], - [ - [ [ [ -2, -1, 1, 3, 0, 0 ], [ -1, 0, 1, 2, 0, 0 ], [ -2, 0, 1, 3, 0, 0 ], [ -2, 0, 1, 4, 0, 0 ] ], 1.625 ] - ], - [ - [ [ [ -2, -1, 1, 3, 0, 0 ], [ -1, 0, 1, 2, 0, 0 ], [ -2, 0, 1, 3, 0, 0 ], [ -1, -1, 1, 3, 1, 0 ] ], 1.25 ] - ], - [ - [ [ [ -2, -1, 1, 3, 0, 0 ], [ -1, 0, 1, 2, 0, 0 ], [ -1, -1, 0, 3, 0, 0 ], [ -1, -1, 1, 3, 1, 0 ] ], 0.75 ] - ], - [ - [ [ [ -2, -1, 1, 3, 0, 0 ], [ -1, 0, 1, 2, 0, 0 ], [ -1, -1, 0, 3, 0, 0 ], [ -1, -1, 0, 4, 0, 0 ] ], 1.125 ] - ], - [ - [ [ [ -1, 0, 1, 2, 0, -1 ], [ -1, 0, 1, 2, 0, 0 ], [ -1, -1, 0, 3, 0, 0 ], [ -1, -1, 0, 4, 0, 0 ] ], 0.875 ] - ], - [ - [ [ [ -1, -1, 1, 2, 0, 0 ], [ -1, 0, 1, 2, 0, 0 ], [ -1, -1, 0, 3, 0, 0 ], [ -1, -1, 0, 4, 0, 0 ] ], 1.625 ] - ], - [ - [ [ [ -2, 0, 0, 3, 0, 0 ], [ -1, 0, 1, 2, 0, 0 ], [ -1, -1, 0, 3, 0, 0 ], [ -1, -1, 0, 4, 0, 0 ] ], 1.5 ] - ], - [ - [ [ [ -2, -1, 0, 4, 0, 0 ], [ -1, 0, 1, 2, 0, 0 ], [ -1, -1, 0, 3, 0, 0 ], [ -1, -1, 0, 4, 0, 0 ] ], 1.625 ] - ], - [ - [ [ [ -2, -1, 0, 4, 0, 0 ], [ -1, -1, 1, 3, 0, 0 ], [ -1, -1, 0, 3, 0, 0 ], [ -1, -1, 0, 4, 0, 0 ] ], 1.75 ] - ], - [ - [ [ [ -2, -1, 0, 4, 0, 0 ], [ -1, -1, 1, 3, 0, 0 ], [ -1, -1, 0, 3, 0, 0 ], [ -1, -1, 1, 4, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, -1, 0, 4, 0, 0 ], [ -1, -1, 1, 3, 0, 0 ], [ -1, -1, 0, 3, 0, 0 ], [ -1, 0, 0, 3, 0, 0 ] ], 1.25 ] - ], - [ - [ [ [ -1, -1, 1, 3, -1, 0 ], [ -1, -1, 1, 3, 0, 0 ], [ -1, -1, 0, 3, 0, 0 ], [ -1, 0, 0, 3, 0, 0 ] ], 0.75 ] - ], - [ - [ [ [ -1, -1, 1, 3, -1, 0 ], [ -1, -1, 1, 3, 0, 0 ], [ -2, -1, 1, 3, 0, 1 ], [ -1, 0, 0, 3, 0, 0 ] ], 1.5 ] - ], - [ - [ [ [ -1, -1, 1, 3, -1, 0 ], [ -1, -1, 1, 3, 0, 0 ], [ -1, 0, 0, 3, -1, 0 ], [ -1, 0, 0, 3, 0, 0 ] ], 1.75 ] - ], - [ - [ [ [ -1, -1, 1, 3, -1, 0 ], [ 0, -1, 1, 3, -2, 0 ], [ -1, 0, 0, 3, -1, 0 ], [ -1, 0, 0, 3, 0, 0 ] ], 1.25 ] - ], - [ - [ [ [ -1, -1, 1, 3, -1, 0 ], [ -1, 0, 1, 3, -1, 0 ], [ -1, 0, 0, 3, -1, 0 ], [ -1, 0, 0, 3, 0, 0 ] ], 1.5 ] - ], - [ - [ [ [ -1, -1, 1, 3, -1, 0 ], [ 0, -1, 0, 3, -1, 0 ], [ -1, 0, 0, 3, -1, 0 ], [ -1, 0, 0, 3, 0, 0 ] ], 1.75 ] - ], - [ - [ [ [ -1, -1, 0, 3, 0, 0 ], [ 0, -1, 0, 3, -1, 0 ], [ -1, 0, 0, 3, -1, 0 ], [ -1, 0, 0, 3, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 0, 0, 3, 1, 0 ], [ 0, -1, 0, 3, -1, 0 ], [ -1, 0, 0, 3, -1, 0 ], [ -1, 0, 0, 3, 0, 0 ] ], 1.375 ] - ], - [ - [ [ [ -2, 0, 0, 3, 1, 0 ], [ 0, -1, 0, 3, -1, 0 ], [ -1, 0, 0, 3, -1, 0 ], [ -1, 1, 0, 3, -1, 0 ] ], 1.875 ] - ], - [ - [ [ [ -2, 1, 0, 3, 0, 0 ], [ 0, -1, 0, 3, -1, 0 ], [ -1, 0, 0, 3, -1, 0 ], [ -1, 1, 0, 3, -1, 0 ] ], 1.375 ] - ], - [ - [ [ [ -2, 1, 0, 3, 0, 0 ], [ 0, -1, 0, 3, -1, 0 ], [ -1, 0, 0, 3, -1, 0 ], [ -1, 0, 0, 3, -1, 1 ] ], 1.75 ] - ], - [ - [ [ [ -2, 1, 0, 3, 0, 0 ], [ 0, -1, 0, 3, -1, 0 ], [ -1, -1, 0, 4, -1, 0 ], [ -1, 0, 0, 3, -1, 1 ] ], 1.625 ] - ], - [ - [ [ [ 0, -1, -1, 3, -1, 0 ], [ 0, -1, 0, 3, -1, 0 ], [ -1, -1, 0, 4, -1, 0 ], [ -1, 0, 0, 3, -1, 1 ] ], 0.625 ] - ], - [ - [ [ [ 0, -1, -1, 3, -1, 0 ], [ 0, -1, 0, 3, -1, 0 ], [ -1, -1, 0, 4, -1, 0 ], [ 1, -2, 0, 3, -1, 0 ] ], 1.125 ] - ], - [ - [ [ [ 0, -1, -1, 3, -1, 0 ], [ 0, -1, 0, 3, -1, 0 ], [ 1, -2, 0, 3, -2, 0 ], [ 1, -2, 0, 3, -1, 0 ] ], 0.75 ] - ], - [ - [ [ [ 1, -3, 0, 3, -1, 0 ], [ 0, -1, 0, 3, -1, 0 ], [ 1, -2, 0, 3, -2, 0 ], [ 1, -2, 0, 3, -1, 0 ] ], 0.875 ] - ], - [ - [ [ [ 1, -3, 0, 3, -1, 0 ], [ 0, -1, 0, 3, -1, 0 ], [ 0, -2, 0, 3, -1, 1 ], [ 1, -2, 0, 3, -1, 0 ] ], 0.875 ] - ], - [ - [ [ [ 1, -3, 0, 3, -1, 0 ], [ 0, -1, 0, 3, -1, 0 ], [ 2, -3, 0, 3, -1, -1 ], [ 1, -2, 0, 3, -1, 0 ] ], 1.375 ] - ], - [ - [ [ [ 1, -2, 0, 3, -2, 0 ], [ 0, -1, 0, 3, -1, 0 ], [ 2, -3, 0, 3, -1, -1 ], [ 1, -2, 0, 3, -1, 0 ] ], 1.125 ] - ], - [ - [ [ [ 1, -2, 0, 3, -2, 0 ], [ 1, -2, -1, 3, -1, 0 ], [ 2, -3, 0, 3, -1, -1 ], [ 1, -2, 0, 3, -1, 0 ] ], 1 ] - ], - [ - [ [ [ 1, -2, 0, 3, -2, 0 ], [ 2, -2, 0, 2, -2, 0 ], [ 2, -3, 0, 3, -1, -1 ], [ 1, -2, 0, 3, -1, 0 ] ], 0.75 ] - ], - [ - [ [ [ 1, -2, 0, 3, -2, 0 ], [ 2, -2, 0, 2, -2, 0 ], [ 0, -2, 0, 4, -1, 0 ], [ 1, -2, 0, 3, -1, 0 ] ], 1.75 ] - ], - [ - [ [ [ 1, -2, 0, 3, -2, 0 ], [ 2, -2, 0, 2, -2, 0 ], [ 0, -2, 0, 4, -1, 0 ], [ 2, -2, 0, 3, -3, 0 ] ], 1.5 ] - ], - [ - [ [ [ 1, -2, 0, 3, -2, 0 ], [ 1, -2, 1, 3, -2, 0 ], [ 0, -2, 0, 4, -1, 0 ], [ 2, -2, 0, 3, -3, 0 ] ], 1.625 ] - ], - [ - [ [ [ 1, -2, 0, 3, -2, 0 ], [ 1, -2, 0, 3, -1, 0 ], [ 0, -2, 0, 4, -1, 0 ], [ 2, -2, 0, 3, -3, 0 ] ], 1 ] - ], - [ - [ [ [ 1, -1, 0, 3, -3, 0 ], [ 1, -2, 0, 3, -1, 0 ], [ 0, -2, 0, 4, -1, 0 ], [ 2, -2, 0, 3, -3, 0 ] ], 1.625 ] - ], - [ - [ [ [ 2, -2, -1, 3, -3, 0 ], [ 1, -2, 0, 3, -1, 0 ], [ 0, -2, 0, 4, -1, 0 ], [ 2, -2, 0, 3, -3, 0 ] ], 0.75 ] - ], - [ - [ [ [ -1, -3, 0, 3, -1, 0 ], [ 1, -2, 0, 3, -1, 0 ], [ 0, -2, 0, 4, -1, 0 ], [ 2, -2, 0, 3, -3, 0 ] ], 1.125 ] - ], - [ - [ [ [ -1, -3, 0, 3, -1, 0 ], [ 1, -2, 0, 3, -1, 0 ], [ 2, -4, 0, 3, -1, 0 ], [ 2, -2, 0, 3, -3, 0 ] ], 0.875 ] - ], - [ - [ [ [ -1, -3, 0, 3, -1, 0 ], [ 1, -3, 0, 3, -1, 1 ], [ 2, -4, 0, 3, -1, 0 ], [ 2, -2, 0, 3, -3, 0 ] ], 1.25 ] - ], - [ - [ [ [ -1, -3, 0, 3, -1, 0 ], [ 1, -3, 0, 3, -1, 1 ], [ 2, -4, 0, 3, -1, 0 ], [ 2, -4, 1, 3, -1, 0 ] ], 0.875 ] - ], - [ - [ [ [ -1, -3, 0, 3, -1, 0 ], [ 1, -3, 0, 3, -1, 1 ], [ 2, -4, 0, 3, -1, 0 ], [ 1, -4, 0, 3, -1, 0 ] ], 1.875 ] - ], - [ - [ [ [ -1, -3, 0, 3, -1, 0 ], [ 2, -4, 1, 3, -1, 0 ], [ 2, -4, 0, 3, -1, 0 ], [ 1, -4, 0, 3, -1, 0 ] ], 1.625 ] - ], - [ - [ [ [ -1, -3, 0, 3, -1, 0 ], [ 0, -4, 0, 3, -1, 0 ], [ 2, -4, 0, 3, -1, 0 ], [ 1, -4, 0, 3, -1, 0 ] ], 0.875 ] - ], - [ - [ [ [ -1, -3, 0, 3, -1, 0 ], [ -1, -2, 0, 3, -1, 0 ], [ 2, -4, 0, 3, -1, 0 ], [ 1, -4, 0, 3, -1, 0 ] ], 1.625 ] - ], - [ - [ [ [ -1, -3, 0, 3, -1, 0 ], [ -1, -2, 0, 3, -1, 0 ], [ 2, -4, 0, 3, -1, 0 ], [ 0, -2, 0, 3, -1, 0 ] ], 1.75 ] - ], - [ - [ [ [ -1, -3, 0, 3, -1, 0 ], [ 0, -3, -1, 3, -1, 0 ], [ 2, -4, 0, 3, -1, 0 ], [ 0, -2, 0, 3, -1, 0 ] ], 0.875 ] - ], - [ - [ [ [ -2, -2, 0, 3, 0, 0 ], [ 0, -3, -1, 3, -1, 0 ], [ 2, -4, 0, 3, -1, 0 ], [ 0, -2, 0, 3, -1, 0 ] ], 0.625 ] - ], - [ - [ [ [ -1, -4, 0, 3, -1, 1 ], [ 0, -3, -1, 3, -1, 0 ], [ 2, -4, 0, 3, -1, 0 ], [ 0, -2, 0, 3, -1, 0 ] ], 0.875 ] - ], - [ - [ [ [ -1, -4, 0, 3, -1, 1 ], [ 1, -5, 0, 3, -1, 0 ], [ 2, -4, 0, 3, -1, 0 ], [ 0, -2, 0, 3, -1, 0 ] ], 1.375 ] - ], - [ - [ [ [ -1, -4, 0, 3, -1, 1 ], [ 1, -5, 0, 3, -1, 0 ], [ 2, -4, 0, 3, -1, 0 ], [ 1, -5, 0, 4, -1, 0 ] ], 1.625 ] - ], - [ - [ [ [ -1, -4, 0, 3, -1, 1 ], [ 1, -5, 0, 3, -1, 0 ], [ 2, -4, 0, 3, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 1 ] - ], - [ - [ [ [ 1, -6, 0, 3, -1, 0 ], [ 1, -5, 0, 3, -1, 0 ], [ 2, -4, 0, 3, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 0.625 ] - ], - [ - [ [ [ 1, -6, 0, 3, -1, 0 ], [ 1, -5, 0, 3, -1, 0 ], [ 3, -5, -1, 3, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 0.625 ] - ], - [ - [ [ [ 1, -6, 0, 3, -1, 0 ], [ 1, -5, 0, 3, -1, 0 ], [ 3, -6, 1, 3, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 1.625 ] - ], - [ - [ [ [ 0, -6, 1, 3, -1, 1 ], [ 1, -5, 0, 3, -1, 0 ], [ 3, -6, 1, 3, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 1.25 ] - ], - [ - [ [ [ 0, -6, 1, 3, -1, 1 ], [ 0, -5, 1, 3, -1, 1 ], [ 3, -6, 1, 3, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 0.75 ] - ], - [ - [ [ [ 0, -6, 1, 4, -1, 0 ], [ 0, -5, 1, 3, -1, 1 ], [ 3, -6, 1, 3, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 0.75 ] - ], - [ - [ [ [ 0, -6, 1, 4, -1, 0 ], [ 0, -5, 1, 4, -1, 0 ], [ 3, -6, 1, 3, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 0.875 ] - ], - [ - [ [ [ 0, -6, 1, 4, -1, 0 ], [ 0, -5, 1, 4, -1, 0 ], [ 2, -6, 2, 4, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 1 ] - ], - [ - [ [ [ 0, -6, 1, 4, -1, 0 ], [ 0, -5, 1, 4, -1, 0 ], [ 3, -7, 1, 4, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 1 ] - ], - [ - [ [ [ 0, -6, 1, 4, -1, 0 ], [ 2, -7, 1, 3, -1, 0 ], [ 3, -7, 1, 4, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 1.25 ] - ], - [ - [ [ [ 1, -7, 0, 4, -1, 0 ], [ 2, -7, 1, 3, -1, 0 ], [ 3, -7, 1, 4, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 0.625 ] - ], - [ - [ [ [ 0, -7, 1, 5, -1, 0 ], [ 2, -7, 1, 3, -1, 0 ], [ 3, -7, 1, 4, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 0.75 ] - ], - [ - [ [ [ 0, -7, 1, 5, -1, 0 ], [ 2, -7, 1, 3, -1, 0 ], [ 4, -7, 1, 2, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 1 ] - ], - [ - [ [ [ 0, -7, 1, 5, -1, 0 ], [ 2, -5, 0, 3, -1, -1 ], [ 4, -7, 1, 2, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 1.625 ] - ], - [ - [ [ [ 3, -7, 1, 2, -2, 0 ], [ 2, -5, 0, 3, -1, -1 ], [ 4, -7, 1, 2, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 1.75 ] - ], - [ - [ [ [ 3, -7, 1, 2, -2, 0 ], [ 2, -5, 0, 3, -1, -1 ], [ 5, -7, 1, 2, -3, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 0.875 ] - ], - [ - [ [ [ 3, -7, 1, 2, -2, 0 ], [ 2, -5, 0, 3, -1, -1 ], [ 2, -3, 0, 3, -1, -1 ], [ 2, -4, 0, 3, -1, -1 ] ], 1.25 ] - ], - [ - [ [ [ 3, -7, 1, 2, -2, 0 ], [ 2, -5, 0, 3, -1, -1 ], [ 2, -4, 0, 3, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 1.75 ] - ], - [ - [ [ [ 2, -5, -1, 3, -1, -1 ], [ 2, -5, 0, 3, -1, -1 ], [ 2, -4, 0, 3, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], 1.625 ] - ], - [ - [ [ [ 2, -5, -1, 3, -1, -1 ], [ 2, -5, 0, 3, -1, -1 ], [ 2, -4, 0, 3, -1, 0 ], [ 3, -5, -1, 3, -1, -1 ] ], 1.25 ] - ], - [ - [ [ [ 2, -5, -1, 3, -1, -1 ], [ 2, -5, 0, 3, -1, -1 ], [ 2, -4, 0, 3, -1, 0 ], [ 2, -5, 0, 4, -1, -1 ] ], 1.375 ] - ], - [ - [ [ [ 2, -5, -1, 3, -1, -1 ], [ 2, -5, 0, 3, -1, -1 ], [ 2, -4, 0, 3, -1, 0 ], [ 4, -5, -1, 2, -1, -1 ] ], 1.625 ], - [ [ [ "Rest" ], [ 2, -5, 0, 3, -1, -1 ], [ 2, -4, 0, 3, -1, 0 ], [ 4, -5, -1, 2, -1, -1 ] ], 1.125 ], - [ [ [ "Rest" ], [ 2, -5, 0, 3, -1, -1 ], [ "Rest" ], [ 4, -5, -1, 2, -1, -1 ] ], 1.75 ], - [ [ [ "Rest" ], [ 2, -5, 0, 3, -1, -1 ], [ "Rest" ], [ "Rest" ] ], 1.5 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3.0 ] - ] - ] -], -"last_changes": -[ - [ [ 3, -7, 1, 2, -2, 0 ], [ 2, -5, 0, 3, -1, -1 ], [ 2, -4, 0, 3, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], - [ [ 2, -5, -1, 3, -1, -1 ], [ 2, -5, 0, 3, -1, -1 ], [ 2, -4, 0, 3, -1, 0 ], [ 2, -4, 0, 3, -1, -1 ] ], - [ [ 2, -5, -1, 3, -1, -1 ], [ 2, -5, 0, 3, -1, -1 ], [ 2, -4, 0, 3, -1, 0 ], [ 3, -5, -1, 3, -1, -1 ] ], - [ [ 2, -5, -1, 3, -1, -1 ], [ 2, -5, 0, 3, -1, -1 ], [ 2, -4, 0, 3, -1, 0 ], [ 2, -5, 0, 4, -1, -1 ] ], - [ [ 2, -5, -1, 3, -1, -1 ], [ 2, -5, 0, 3, -1, -1 ], [ 2, -4, 0, 3, -1, 0 ], [ 4, -5, -1, 2, -1, -1 ] ] -], -"cur_uid": "55f9b81e", -"ref_uid": "726a40c7", -"order_seed": 540514, -"dur_seed": 331257, -"motifs_seed": 728928, -"entrances_probs_vals": [ 0, 0, 0, 0.66, 1.8406593406593, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 0.66, 1.8406593406593, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 0.66, 1.8406593406593, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2467, 2400 ], [ -1167, 2400 ], [ -702, 2400 ], [ -702, 2400 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.090534979423868, 0.92613636363636, 0.17489711934156, 0.079545454545455, 0.37037037037037, 0, 0.7201646090535, 0, 1, 0 ], -"passages_weights": [ 0.63, 0.62, 1, 0.41, 1 ], -"hd_exp": 3.09, -"hd_invert": 0, -"order": -[ - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 1, 3, 2 ], [ 0 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 1, 3, 2 ], [ 0 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 2, 0, 3 ], [ 1 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 1, 3, 2 ], [ 0 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 1, 3, 2 ], [ 0 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ] -], -"sus_weights": [ 0, 0, 0.61 ], -"order_size": [ 100, 100 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/577cf188/577cf188_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3/577cf188/577cf188_code.scd deleted file mode 100644 index 5a3854b..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/577cf188/577cf188_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/577cf188/577cf188_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3/577cf188/577cf188_mus_model.json deleted file mode 100644 index b37c8be..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/577cf188/577cf188_mus_model.json +++ /dev/null @@ -1,198 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 2.375 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.875 ] - ], - [ - [ [ [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.5 ] - ], - [ - [ [ [ 0, -1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.125 ] - ], - [ - [ [ [ 1, -2, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.625 ] - ], - [ - [ [ [ 0, -1, 1, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 2.5 ] - ], - [ - [ [ [ 0, -1, 1, 0, -1, 0 ], [ 0, 0, 1, 0, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 2 ] - ], - [ - [ [ [ 0, -1, 1, 0, -1, 0 ], [ 0, -1, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 2.625 ] - ], - [ - [ [ [ 0, -1, 1, 0, -1, 0 ], [ 0, -1, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, -1, 0 ] ], 1.125 ] - ], - [ - [ [ [ 0, -1, 1, 0, -1, 0 ], [ 0, -1, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, -1, 0 ] ], 1.875 ] - ], - [ - [ [ [ -1, 0, 2, 0, -1, 0 ], [ 0, -1, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, -1, 0 ] ], 1.125 ] - ], - [ - [ [ [ 0, -2, 1, 0, 0, 0 ], [ 0, -1, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, -1, 0 ] ], 1.625 ] - ], - [ - [ [ [ 0, -2, 1, 0, 0, 0 ], [ 0, -1, 1, 0, 0, 0 ], [ 0, -2, 1, 1, 0, 0 ], [ 0, 0, 1, 0, -1, 0 ] ], 1.375 ] - ], - [ - [ [ [ 0, -2, 1, 0, 0, 0 ], [ 0, -1, 1, 0, 0, 0 ], [ 1, -1, 1, -1, 0, 0 ], [ 0, 0, 1, 0, -1, 0 ] ], 1.875 ] - ], - [ - [ [ [ 0, 0, 1, -1, -1, 0 ], [ 0, -1, 1, 0, 0, 0 ], [ 1, -1, 1, -1, 0, 0 ], [ 0, 0, 1, 0, -1, 0 ] ], 2.5 ] - ], - [ - [ [ [ 0, 0, 1, -1, -1, 0 ], [ -1, 0, 1, 1, -1, 0 ], [ 1, -1, 1, -1, 0, 0 ], [ 0, 0, 1, 0, -1, 0 ] ], 2 ] - ], - [ - [ [ [ 0, 0, 1, -1, -1, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 1, -1, 1, -1, 0, 0 ], [ 0, 0, 1, 0, -1, 0 ] ], 1.25 ] - ], - [ - [ [ [ 0, 0, 1, -1, -1, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 1, -1, 1, -1, 0, 0 ], [ 1, 0, 1, -1, 0, 0 ] ], 2 ] - ], - [ - [ [ [ 0, 0, 1, -1, -1, 0 ], [ 1, 0, 2, -1, 0, 0 ], [ 1, -1, 1, -1, 0, 0 ], [ 1, 0, 1, -1, 0, 0 ] ], 2.5 ] - ], - [ - [ [ [ 0, 0, 1, -1, -1, 0 ], [ 1, 0, 2, -1, 0, 0 ], [ 0, 0, 2, -1, 0, 0 ], [ 1, 0, 1, -1, 0, 0 ] ], 2.375 ] - ], - [ - [ [ [ 0, 0, 1, -1, -1, 0 ], [ 1, 0, 2, -1, 0, 0 ], [ 0, 0, 2, -1, 0, 0 ], [ 0, 1, 2, -1, 0, 0 ] ], 2.125 ] - ], - [ - [ [ [ 0, 0, 1, -1, -1, 0 ], [ 1, 0, 2, -1, 0, 0 ], [ 0, 0, 1, -1, -1, 1 ], [ 0, 1, 2, -1, 0, 0 ] ], 1.375 ] - ], - [ - [ [ [ 0, 0, 1, -1, -1, 0 ], [ 1, 0, 2, -1, 0, 0 ], [ 0, 1, 2, -1, 0, -1 ], [ 0, 1, 2, -1, 0, 0 ] ], 1.25 ] - ], - [ - [ [ [ 0, 1, 2, -1, 0, -2 ], [ 1, 0, 2, -1, 0, 0 ], [ 0, 1, 2, -1, 0, -1 ], [ 0, 1, 2, -1, 0, 0 ] ], 2.875 ] - ], - [ - [ [ [ 0, 1, 2, -1, 0, -2 ], [ 1, 1, 2, -1, 0, -1 ], [ 0, 1, 2, -1, 0, -1 ], [ 0, 1, 2, -1, 0, 0 ] ], 2.5 ] - ], - [ - [ [ [ 0, 1, 2, -1, 0, -2 ], [ 1, 1, 2, -1, 0, -1 ], [ 0, 1, 2, -1, 0, -1 ], [ 2, 1, 2, -1, 0, -3 ] ], 1.875 ] - ], - [ - [ [ [ 0, 1, 2, -1, 0, -2 ], [ 3, 1, 2, -1, 0, -4 ], [ 0, 1, 2, -1, 0, -1 ], [ 2, 1, 2, -1, 0, -3 ] ], 1.375 ] - ], - [ - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 3, 1, 2, -1, 0, -4 ], [ 0, 1, 2, -1, 0, -1 ], [ 2, 1, 2, -1, 0, -3 ] ], 2.25 ] - ], - [ - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 3, 1, 2, -1, 0, -4 ], [ 0, 1, 2, -1, 0, -1 ], [ 2, 2, 2, -1, 0, -4 ] ], 2 ] - ], - [ - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 3, 1, 2, -1, 0, -4 ], [ 0, 1, 2, -1, 0, -1 ], [ 2, 1, 2, -3, 0, -1 ] ], 2 ] - ], - [ - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 3, 1, 2, -1, 0, -4 ], [ 0, 1, 2, -1, 0, -1 ], [ 0, 1, 3, -1, 0, -1 ] ], 2 ] - ], - [ - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 2, 2, -2, 0, -1 ], [ 0, 1, 2, -1, 0, -1 ], [ 0, 1, 3, -1, 0, -1 ] ], 0 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 2, 2, -2, 0, -1 ], [ 2, 1, 2, -3, 0, -1 ], [ 0, 1, 3, -1, 0, -1 ] ], 0 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 2, 2, -2, 0, -1 ], [ 2, 1, 2, -3, 0, -1 ], [ 2, 1, 1, -2, 0, -1 ] ], 2.625 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 2, 1, 2, -2, -1, -1 ], [ 2, 1, 2, -3, 0, -1 ], [ 2, 1, 1, -2, 0, -1 ] ], 0 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 2, 1, 2, -2, -1, -1 ], [ 1, 1, 2, -1, 0, -1 ], [ 2, 1, 1, -2, 0, -1 ] ], 0 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 2, 1, 2, -2, -1, -1 ], [ 1, 1, 2, -1, 0, -1 ], [ 3, 1, 2, -3, 0, -1 ] ], 1.625 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 1, 2, -2, 1, -1 ], [ 1, 1, 2, -1, 0, -1 ], [ 3, 1, 2, -3, 0, -1 ] ], 0 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 1, 2, -2, 1, -1 ], [ 1, 1, 2, -2, 0, 0 ], [ 3, 1, 2, -3, 0, -1 ] ], 0 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 1, 2, -2, 1, -1 ], [ 1, 1, 2, -2, 0, 0 ], [ 1, 1, 3, -2, 0, -1 ] ], 1.75 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 2, 0, 2, -2, 0, -1 ], [ 1, 1, 2, -2, 0, 0 ], [ 1, 1, 3, -2, 0, -1 ] ], 0 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 2, 0, 2, -2, 0, -1 ], [ 1, 2, 2, -2, 0, -1 ], [ 1, 1, 3, -2, 0, -1 ] ], 0 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 2, 0, 2, -2, 0, -1 ], [ 1, 2, 2, -2, 0, -1 ], [ 2, 1, 2, -2, 0, -2 ] ], 1.375 ] - ], - [ - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 0, 2, 2, -1, 0, -1 ], [ 1, 2, 2, -2, 0, -1 ], [ 2, 1, 2, -2, 0, -2 ] ], 1.625 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 0, 2, 2, -2, 0, 0 ], [ 1, 2, 2, -2, 0, -1 ], [ 2, 1, 2, -2, 0, -2 ] ], 1.625 ] - ], - [ - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 2, 1, 2, -3, 0, -1 ], [ 1, 2, 2, -2, 0, -1 ], [ 2, 1, 2, -2, 0, -2 ] ], 0 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 2, 1, 2, -3, 0, -1 ], [ 2, 1, 2, -2, -1, -1 ], [ 2, 1, 2, -2, 0, -2 ] ], 0 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 2, 1, 2, -3, 0, -1 ], [ 2, 1, 2, -2, -1, -1 ], [ 3, 1, 2, -2, 0, -2 ] ], 2.625 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 0, 2, 2, -2, 0, -1 ], [ 2, 1, 2, -2, -1, -1 ], [ 3, 1, 2, -2, 0, -2 ] ], 0 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 0, 2, 2, -2, 0, -1 ], [ 1, 1, 2, -2, 1, -1 ], [ 3, 1, 2, -2, 0, -2 ] ], 0 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 0, 2, 2, -2, 0, -1 ], [ 1, 1, 2, -2, 1, -1 ], [ 3, 1, 2, -3, 0, -1 ] ], 2.125 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 1, 2, -2, -1, -1 ], [ 1, 1, 2, -2, 1, -1 ], [ 3, 1, 2, -3, 0, -1 ] ], 0 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 1, 2, -2, -1, -1 ], [ 2, 0, 2, -2, 0, -1 ], [ 3, 1, 2, -3, 0, -1 ] ], 0 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 1, 2, -2, -1, -1 ], [ 2, 0, 2, -2, 0, -1 ], [ 2, 1, 2, -2, 0, -1 ] ], 1.5 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 1, 2, -2, 0, -1 ], [ 2, 0, 2, -2, 0, -1 ], [ 2, 1, 2, -2, 0, -1 ] ], 0 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 1, 2, -2, 0, -1 ], [ 1, 1, 3, -2, 0, -1 ], [ 2, 1, 2, -2, 0, -1 ] ], 0 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 1, 2, -2, 0, -1 ], [ 1, 1, 3, -2, 0, -1 ], [ 2, 1, 3, -2, 0, -1 ] ], 2.25 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 1, 2, -2, 0, -1 ], [ "Rest" ], [ 2, 1, 3, -2, 0, -1 ] ], 0 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 1, 2, -2, 0, -1 ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ 0, 1, 2, -2, 0, -1 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 7.0 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 1, 2, -2, -1, -1 ], [ 2, 0, 2, -2, 0, -1 ], [ 3, 1, 2, -3, 0, -1 ] ], - [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 1, 2, -2, -1, -1 ], [ 2, 0, 2, -2, 0, -1 ], [ 2, 1, 2, -2, 0, -1 ] ], - [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 1, 2, -2, 0, -1 ], [ 2, 0, 2, -2, 0, -1 ], [ 2, 1, 2, -2, 0, -1 ] ], - [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 1, 2, -2, 0, -1 ], [ 1, 1, 3, -2, 0, -1 ], [ 2, 1, 2, -2, 0, -1 ] ], - [ [ 0, 1, 2, -2, 0, -1 ], [ 1, 1, 2, -2, 0, -1 ], [ 1, 1, 3, -2, 0, -1 ], [ 2, 1, 3, -2, 0, -1 ] ] -], -"cur_uid": "577cf188", -"ref_uid": "nil", -"order_seed": 755225, -"dur_seed": 543380, -"motifs_seed": 119394, -"entrances_probs_vals": [ 1, 0, 0, 1.1263736263736, 2.83, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 0, 1.1263736263736, 2.83, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 0, 1.1263736263736, 2.83, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1315, 1582.6625386997 ], [ -702.16718266254, 1453 ], [ -386, 1676 ], [ -219, 1694 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 1, 1, 0.66, 0.74, 1 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 2, 0, 3 ], [ 1 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 0 ], [ 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3 ], [ ] ], - [ [ 3, 2, 1 ], [ 1 ], [ ] ], - [ [ 0 ], [ 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3 ], [ ] ] -], -"sus_weights": [ 0, 0, 0.51 ], -"order_size": [ 30, 30 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/5ec14635/5ec14635_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3/5ec14635/5ec14635_code.scd deleted file mode 100644 index f822edb..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/5ec14635/5ec14635_code.scd +++ /dev/null @@ -1,946 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - if(pDistance < 0, {stepFunc.value(abs(pDistance))}, {0.001}); - //stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/5ec14635/5ec14635_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3/5ec14635/5ec14635_mus_model.json deleted file mode 100644 index c4309f6..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/5ec14635/5ec14635_mus_model.json +++ /dev/null @@ -1,163 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ -2, -1, 0, 0, 0, -1 ], [ "Rest" ] ], 0.375 ], - [ [ [ "Rest" ], [ -2, -2, 0, 1, 0, -2 ], [ -2, -1, 0, 0, 0, -1 ], [ "Rest" ] ], 0 ], - [ [ [ -2, -1, 0, 1, 0, -2 ], [ -2, -2, 0, 1, 0, -2 ], [ -2, -1, 0, 0, 0, -1 ], [ "Rest" ] ], 0.5 ], - [ [ [ -2, -1, 0, 1, 0, -2 ], [ -2, -2, 0, 1, 0, -2 ], [ -2, -1, 0, 0, 0, -1 ], [ 1, -2, 0, 2, 0, -2 ] ], 0.125 ] - ], - [ - [ [ [ -2, -1, 0, 1, 0, -2 ], [ -2, -2, 0, 1, 0, -2 ], [ 0, 0, 0, 1, 0, -2 ], [ 1, -2, 0, 2, 0, -2 ] ], 1 ] - ], - [ - [ [ [ -2, -1, 0, 1, 0, -2 ], [ -2, -2, 0, 1, 0, -2 ], [ 0, 0, 0, 1, 0, -2 ], [ 0, 0, 0, 1, 0, -1 ] ], 1.125 ] - ], - [ - [ [ [ -2, -1, 0, 1, 0, -2 ], [ -1, 1, 0, 1, 0, -1 ], [ 0, 0, 0, 1, 0, -2 ], [ 0, 0, 0, 1, 0, -1 ] ], 1.125 ] - ], - [ - [ [ [ -2, -1, 0, 1, 0, -2 ], [ 0, 0, 1, 1, 0, -2 ], [ 0, 0, 0, 1, 0, -2 ], [ 0, 0, 0, 1, 0, -1 ] ], 0.125 ] - ], - [ - [ [ [ -2, -1, 0, 1, 0, -2 ], [ 0, 0, 1, 1, 0, -2 ], [ -1, 0, 1, 1, 0, -1 ], [ 0, 0, 0, 1, 0, -1 ] ], 0.75 ] - ], - [ - [ [ [ -2, -1, 0, 1, 0, -2 ], [ 0, 0, 1, 1, 0, -2 ], [ -1, 0, 1, 2, 0, -2 ], [ 0, 0, 0, 1, 0, -1 ] ], 0.75 ] - ], - [ - [ [ [ -2, -1, 0, 1, 0, -2 ], [ 0, 0, 1, 1, 0, -2 ], [ 0, -1, 0, 2, 0, -2 ], [ 0, 0, 0, 1, 0, -1 ] ], 0 ] - ], - [ - [ [ [ -2, -1, 0, 1, 0, -2 ], [ 0, 0, 1, 1, 0, -2 ], [ -1, 1, 0, 1, 0, -1 ], [ 0, 0, 0, 1, 0, -1 ] ], 0.625 ] - ], - [ - [ [ [ -2, -1, 0, 1, 0, -2 ], [ 0, 0, 1, 1, 0, -2 ], [ -1, 1, 0, 1, 0, -1 ], [ 0, 0, 1, 1, 1, -2 ] ], 1.125 ] - ], - [ - [ [ [ -2, -1, 0, 1, 0, -2 ], [ 0, 0, 1, 1, 0, -2 ], [ -1, 1, 1, 1, 1, -2 ], [ 0, 0, 1, 1, 1, -2 ] ], 1 ] - ], - [ - [ [ [ -2, -1, 0, 1, 0, -2 ], [ 0, 0, 1, 1, 0, -2 ], [ -1, 1, 1, 1, 1, -2 ], [ 1, -1, 0, 1, 1, -2 ] ], 0.625 ] - ], - [ - [ [ [ -2, -1, 0, 1, 0, -2 ], [ 1, -1, 0, 1, 0, -2 ], [ -1, 1, 1, 1, 1, -2 ], [ 1, -1, 0, 1, 1, -2 ] ], 0.75 ] - ], - [ - [ [ [ -1, -1, 0, 2, 1, -2 ], [ 1, -1, 0, 1, 0, -2 ], [ -1, 1, 1, 1, 1, -2 ], [ 1, -1, 0, 1, 1, -2 ] ], 1.125 ] - ], - [ - [ [ [ -1, 0, 1, 1, 1, -2 ], [ 1, -1, 0, 1, 0, -2 ], [ -1, 1, 1, 1, 1, -2 ], [ 1, -1, 0, 1, 1, -2 ] ], 0.25 ] - ], - [ - [ [ [ -1, 0, 1, 1, 1, -2 ], [ -1, 0, 1, 1, 1, -1 ], [ -1, 1, 1, 1, 1, -2 ], [ 1, -1, 0, 1, 1, -2 ] ], 0.25 ] - ], - [ - [ [ [ -1, 0, 1, 1, 1, -2 ], [ -1, 0, 1, 2, 1, -2 ], [ -1, 1, 1, 1, 1, -2 ], [ 1, -1, 0, 1, 1, -2 ] ], 1.125 ] - ], - [ - [ [ [ -1, 0, 1, 1, 1, -2 ], [ -1, 0, 1, 2, 1, -2 ], [ -2, 0, 1, 3, 1, -2 ], [ 1, -1, 0, 1, 1, -2 ] ], 1.125 ] - ], - [ - [ [ [ -1, 0, 1, 1, 1, -2 ], [ -1, 0, 1, 2, 1, -2 ], [ -2, 0, 1, 3, 1, -2 ], [ -1, 0, 1, 3, 0, -2 ] ], 1 ] - ], - [ - [ [ [ -1, 0, 1, 1, 1, -2 ], [ -1, 0, 1, 2, 1, -2 ], [ -2, 0, 1, 3, 1, -2 ], [ 0, -1, 1, 2, 1, -2 ] ], 0.25 ] - ], - [ - [ [ [ -1, 0, 1, 2, 1, -3 ], [ -1, 0, 1, 2, 1, -2 ], [ -2, 0, 1, 3, 1, -2 ], [ 0, -1, 1, 2, 1, -2 ] ], 0.25 ] - ], - [ - [ [ [ -3, 1, 1, 3, 1, -2 ], [ -1, 0, 1, 2, 1, -2 ], [ -2, 0, 1, 3, 1, -2 ], [ 0, -1, 1, 2, 1, -2 ] ], 0 ] - ], - [ - [ [ [ -2, 0, 1, 2, 2, -2 ], [ -1, 0, 1, 2, 1, -2 ], [ -2, 0, 1, 3, 1, -2 ], [ 0, -1, 1, 2, 1, -2 ] ], 1 ] - ], - [ - [ [ [ -2, 0, 1, 2, 2, -2 ], [ -1, 0, 1, 2, 1, -2 ], [ -2, 0, 1, 3, 1, -2 ], [ -1, 0, 0, 3, 1, -2 ] ], 0.75 ] - ], - [ - [ [ [ -2, 0, 1, 2, 2, -2 ], [ -1, 0, 1, 2, 1, -2 ], [ -1, -1, 1, 2, 2, -2 ], [ -1, 0, 0, 3, 1, -2 ] ], 0.625 ] - ], - [ - [ [ [ -1, 0, 1, 2, 0, -2 ], [ -1, 0, 1, 2, 1, -2 ], [ -1, -1, 1, 2, 2, -2 ], [ -1, 0, 0, 3, 1, -2 ] ], 0.125 ] - ], - [ - [ [ [ -1, 0, 1, 2, 0, -2 ], [ -1, 0, 1, 2, 1, -2 ], [ -1, -1, 0, 3, 1, -2 ], [ -1, 0, 0, 3, 1, -2 ] ], 0.75 ] - ], - [ - [ [ [ -1, 0, 1, 2, 0, -2 ], [ 0, 0, 1, 2, -1, -2 ], [ -1, -1, 0, 3, 1, -2 ], [ -1, 0, 0, 3, 1, -2 ] ], 0.25 ] - ], - [ - [ [ [ -1, 0, 1, 2, 0, -2 ], [ 0, -1, 0, 2, 1, -2 ], [ -1, -1, 0, 3, 1, -2 ], [ -1, 0, 0, 3, 1, -2 ] ], 1.25 ] - ], - [ - [ [ [ -1, 0, 1, 2, 0, -2 ], [ 0, -1, 0, 2, 1, -2 ], [ -1, -1, 0, 3, 1, -2 ], [ 0, -1, 0, 2, 2, -2 ] ], 0.625 ], - [ [ [ "Rest" ], [ 0, -1, 0, 2, 1, -2 ], [ -1, -1, 0, 3, 1, -2 ], [ 0, -1, 0, 2, 2, -2 ] ], 0.625 ], - [ [ [ "Rest" ], [ 0, -1, 0, 2, 1, -2 ], [ -1, -1, 0, 3, 1, -2 ], [ "Rest" ] ], 0.375 ], - [ [ [ "Rest" ], [ "Rest" ], [ -1, -1, 0, 3, 1, -2 ], [ "Rest" ] ], 0.875 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.375 ] - ] - ] -], -"last_changes": -[ - [ [ -1, 0, 1, 2, 0, -2 ], [ -1, 0, 1, 2, 1, -2 ], [ -1, -1, 1, 2, 2, -2 ], [ -1, 0, 0, 3, 1, -2 ] ], - [ [ -1, 0, 1, 2, 0, -2 ], [ -1, 0, 1, 2, 1, -2 ], [ -1, -1, 0, 3, 1, -2 ], [ -1, 0, 0, 3, 1, -2 ] ], - [ [ -1, 0, 1, 2, 0, -2 ], [ 0, 0, 1, 2, -1, -2 ], [ -1, -1, 0, 3, 1, -2 ], [ -1, 0, 0, 3, 1, -2 ] ], - [ [ -1, 0, 1, 2, 0, -2 ], [ 0, -1, 0, 2, 1, -2 ], [ -1, -1, 0, 3, 1, -2 ], [ -1, 0, 0, 3, 1, -2 ] ], - [ [ -1, 0, 1, 2, 0, -2 ], [ 0, -1, 0, 2, 1, -2 ], [ -1, -1, 0, 3, 1, -2 ], [ 0, -1, 0, 2, 2, -2 ] ] -], -"cur_uid": "5ec14635", -"ref_uid": "7c2de94c", -"order_seed": 733231, -"dur_seed": 711733, -"motifs_seed": 934821, -"entrances_probs_vals": [ 0, 0, 0, 0, 1.2087912087912, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 0, 1.2087912087912, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 0, 1.2087912087912, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2170, 338 ], [ -2373.9938080495, 1453 ], [ -1650, 1676 ], [ -1370.8978328173, 1694 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 1, 0, 0.2, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 1, 3, 2 ], [ 0 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 2, 0, 3 ], [ 1 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ] -], -"sus_weights": [ 0, 0, 0.61 ], -"order_size": [ 30, 30 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/69c568c6/69c568c6_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3/69c568c6/69c568c6_code.scd deleted file mode 100644 index a40da01..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/69c568c6/69c568c6_code.scd +++ /dev/null @@ -1,973 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - - - //isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/69c568c6/69c568c6_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3/69c568c6/69c568c6_mus_model.json deleted file mode 100644 index a490727..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/69c568c6/69c568c6_mus_model.json +++ /dev/null @@ -1,535 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 1.625 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.125 ], - [ [ [ 1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 1, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0.625 ], - [ [ [ 1, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0.75 ] - ], - [ - [ [ [ 1, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ] ], 1.25 ] - ], - [ - [ [ [ 1, 0, 0, 0, 0, 0 ], [ -2, 2, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ] ], 1.625 ] - ], - [ - [ [ [ 0, 1, 0, 0, 0, 0 ], [ -2, 2, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ] ], 0.75 ] - ], - [ - [ [ [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, -1, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ] ], 1.125 ], - [ [ [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, -1, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 1.125 ] - ], - [ - [ [ [ 1, 0, -1, 0, 0, 0 ], [ -1, 1, -1, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 0.5 ], - [ [ [ 1, 0, -1, 0, 0, 0 ], [ -1, 1, -1, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 0.875 ], - [ [ [ 1, 0, -1, 0, 0, 0 ], [ -1, 1, -1, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 1.5 ] - ], - [ - [ [ [ 1, 0, -1, 0, 0, 0 ], [ -1, 1, -1, 0, 0, 0 ], [ -1, 2, -1, 0, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 2, -1, 0, 0, 0 ], [ -1, 1, -1, 0, 0, 0 ], [ -1, 2, -1, 0, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 0.875 ] - ], - [ - [ [ [ 0, 2, -1, 0, 0, 0 ], [ 0, 1, -1, -1, 0, 0 ], [ -1, 2, -1, 0, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 1.375 ], - [ [ [ -2, 2, -1, -1, 0, 0 ], [ 0, 1, -1, -1, 0, 0 ], [ -1, 2, -1, 0, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 0.875 ], - [ [ [ -2, 2, -1, -1, 0, 0 ], [ 0, 1, -1, -1, 0, 0 ], [ 0, 2, -1, -1, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 0.5 ] - ], - [ - [ [ [ -2, 2, -1, -1, 0, 0 ], [ 0, 1, -1, -1, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 1.75 ], - [ [ [ -2, 1, -1, -1, 0, 1 ], [ 0, 1, -1, -1, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, -1, -1, 0, 1 ], [ 1, 1, -1, -2, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 1.25 ] - ], - [ - [ [ [ -2, 1, -1, -1, 0, 1 ], [ 1, 1, -1, -2, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 0.625 ], - [ [ [ -2, 1, -1, -1, 0, 1 ], [ -1, 2, -1, -1, 0, 1 ], [ 1, 0, -1, -1, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 0.875 ] - ], - [ - [ [ [ -2, 1, -1, -1, 0, 1 ], [ 0, 1, -2, -1, 0, 1 ], [ 1, 0, -1, -1, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 1.25 ] - ], - [ - [ [ [ -2, 1, -1, -1, 0, 1 ], [ 1, 1, -1, -1, -1, 0 ], [ 1, 0, -1, -1, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 0.75 ], - [ [ [ -2, 1, -1, -1, 0, 1 ], [ 1, 1, -1, -1, -1, 0 ], [ 0, 2, -1, -1, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 0.875 ] - ], - [ - [ [ [ -1, 2, -1, -2, 0, 0 ], [ 1, 1, -1, -1, -1, 0 ], [ 0, 2, -1, -1, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 1.625 ] - ], - [ - [ [ [ -1, 2, -1, -2, 0, 0 ], [ -1, 2, -1, -1, 0, 0 ], [ 0, 2, -1, -1, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 1.375 ] - ], - [ - [ [ [ -1, 2, -1, -2, 0, 0 ], [ -1, 2, -1, -1, 0, 0 ], [ 1, 2, -1, -2, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 1.125 ], - [ [ [ -1, 2, -1, -2, 0, 0 ], [ -1, 2, -1, -1, 0, 0 ], [ 1, 2, -1, -2, 0, 0 ], [ 0, 2, -1, -1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 2, -1, -2, 0, 0 ], [ 0, 2, -1, -2, 0, 0 ], [ 1, 2, -1, -2, 0, 0 ], [ 0, 2, -1, -1, 0, 0 ] ], 1.625 ], - [ [ [ -1, 2, -1, -2, 0, 0 ], [ 0, 2, -1, -2, 0, 0 ], [ 0, 2, 0, -1, 0, 0 ], [ 0, 2, -1, -1, 0, 0 ] ], 0.75 ] - ], - [ - [ [ [ -1, 2, -1, -2, 0, 0 ], [ -1, 2, 0, -1, 0, 0 ], [ 0, 2, 0, -1, 0, 0 ], [ 0, 2, -1, -1, 0, 0 ] ], 1.375 ], - [ [ [ -1, 2, -1, -2, 0, 0 ], [ -1, 2, 0, -1, 0, 0 ], [ 1, 2, 0, -2, 0, 0 ], [ 0, 2, -1, -1, 0, 0 ] ], 1.75 ] - ], - [ - [ [ [ -1, 2, -1, -2, 0, 0 ], [ -1, 2, 0, -1, 0, 0 ], [ 0, 2, -1, -2, 1, 0 ], [ 0, 2, -1, -1, 0, 0 ] ], 1 ], - [ [ [ -1, 2, -1, -2, 0, 0 ], [ 1, 2, -1, -2, 0, -1 ], [ 0, 2, -1, -2, 1, 0 ], [ 0, 2, -1, -1, 0, 0 ] ], 1.125 ], - [ [ [ -1, 2, -1, -2, 0, 0 ], [ 1, 2, -1, -2, 0, -1 ], [ 0, 2, -1, -2, 1, 0 ], [ 1, 2, -1, -2, 0, 0 ] ], 1.125 ] - ], - [ - [ [ [ -1, 2, -1, -2, 0, 0 ], [ 1, 2, -1, -2, 0, -1 ], [ 0, 3, -1, -2, 0, 0 ], [ 1, 2, -1, -2, 0, 0 ] ], 1.375 ], - [ [ [ -1, 2, -1, -2, 0, 0 ], [ 1, 2, -1, -2, 0, -1 ], [ 0, 3, -1, -2, 0, 0 ], [ 1, 2, -1, -1, 0, -1 ] ], 1.125 ] - ], - [ - [ [ [ -1, 2, -1, -2, 0, 0 ], [ 1, 2, -1, -2, 0, -1 ], [ 0, 3, -1, -2, 0, 0 ], [ 1, 3, -2, -2, 0, 0 ] ], 0.75 ], - [ [ [ -1, 2, -1, -2, 0, 0 ], [ -1, 3, -1, -1, 0, 0 ], [ 0, 3, -1, -2, 0, 0 ], [ 1, 3, -2, -2, 0, 0 ] ], 1.5 ], - [ [ [ -1, 3, -1, -2, 0, 0 ], [ -1, 3, -1, -1, 0, 0 ], [ 0, 3, -1, -2, 0, 0 ], [ 1, 3, -2, -2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 2, -2, -2, 0, 0 ], [ -1, 3, -1, -1, 0, 0 ], [ 0, 3, -1, -2, 0, 0 ], [ 1, 3, -2, -2, 0, 0 ] ], 1.75 ] - ], - [ - [ [ [ 0, 2, -2, -2, 0, 0 ], [ -1, 3, -1, -1, 0, 0 ], [ 1, 2, -2, -2, 0, 0 ], [ 1, 3, -2, -2, 0, 0 ] ], 1.375 ] - ], - [ - [ [ [ 0, 2, -2, -2, 0, 0 ], [ -1, 3, -1, -1, 0, 0 ], [ 0, 3, -2, -2, 0, 0 ], [ 1, 3, -2, -2, 0, 0 ] ], 1.625 ], - [ [ [ 0, 2, -2, -2, 0, 0 ], [ 0, 2, -2, -1, 0, 0 ], [ 0, 3, -2, -2, 0, 0 ], [ 1, 3, -2, -2, 0, 0 ] ], 1.75 ], - [ [ [ 0, 2, -2, -2, 0, 0 ], [ 0, 2, -2, -1, 0, 0 ], [ 0, 3, -2, -2, 0, 0 ], [ 1, 2, -2, -2, 0, 1 ] ], 1 ] - ], - [ - [ [ [ 0, 1, -2, -2, 0, 1 ], [ 0, 2, -2, -1, 0, 0 ], [ 0, 3, -2, -2, 0, 0 ], [ 1, 2, -2, -2, 0, 1 ] ], 1.875 ], - [ [ [ 0, 1, -2, -2, 0, 1 ], [ 0, 2, -1, -2, 0, 1 ], [ 0, 3, -2, -2, 0, 0 ], [ 1, 2, -2, -2, 0, 1 ] ], 0.5 ], - [ [ [ 0, 1, -2, -2, 0, 1 ], [ 0, 2, -1, -2, 0, 1 ], [ 0, 2, -2, -2, 0, 1 ], [ 1, 2, -2, -2, 0, 1 ] ], 0.875 ] - ], - [ - [ [ [ 0, 1, -2, -2, 0, 1 ], [ 0, 2, -1, -2, 0, 1 ], [ 0, 1, -2, -2, 0, 2 ], [ 1, 2, -2, -2, 0, 1 ] ], 1.375 ], - [ [ [ 0, 1, -2, -2, 0, 1 ], [ 0, 2, -1, -2, 0, 1 ], [ 0, 1, -2, -2, 0, 2 ], [ 1, 1, -2, -2, 0, 2 ] ], 0.625 ] - ], - [ - [ [ [ 0, 1, -2, -2, 0, 1 ], [ 0, 2, -1, -2, 0, 1 ], [ 0, 1, -2, -2, 0, 2 ], [ 1, 2, -1, -2, 0, 1 ] ], 0.625 ], - [ [ [ -1, 1, -1, -2, 0, 1 ], [ 0, 2, -1, -2, 0, 1 ], [ 0, 1, -2, -2, 0, 2 ], [ 1, 2, -1, -2, 0, 1 ] ], 0.5 ] - ], - [ - [ [ [ -1, 1, -1, -2, 0, 1 ], [ 1, 1, -2, -2, 0, 1 ], [ 0, 1, -2, -2, 0, 2 ], [ 1, 2, -1, -2, 0, 1 ] ], 0.75 ] - ], - [ - [ [ [ -1, 1, -1, -2, 0, 1 ], [ 1, 1, -2, -2, 0, 1 ], [ 0, 1, -1, -2, 1, 1 ], [ 1, 2, -1, -2, 0, 1 ] ], 0.875 ] - ], - [ - [ [ [ -1, 1, -1, -2, 0, 1 ], [ 1, 1, -2, -2, 0, 1 ], [ 0, 2, -1, -2, 0, 1 ], [ 1, 2, -1, -2, 0, 1 ] ], 1.5 ], - [ [ [ -2, 3, -1, -2, 0, 1 ], [ 1, 1, -2, -2, 0, 1 ], [ 0, 2, -1, -2, 0, 1 ], [ 1, 2, -1, -2, 0, 1 ] ], 1.125 ] - ], - [ - [ [ [ -1, 2, -2, -2, 0, 1 ], [ 1, 1, -2, -2, 0, 1 ], [ 0, 2, -1, -2, 0, 1 ], [ 1, 2, -1, -2, 0, 1 ] ], 0.625 ], - [ [ [ -1, 2, -2, -2, 0, 1 ], [ 1, 1, -2, -2, 0, 1 ], [ 0, 2, -1, -2, 0, 1 ], [ 1, 2, -2, -2, 0, 1 ] ], 1.75 ], - [ [ [ -1, 2, -2, -2, 0, 1 ], [ 1, 1, -2, -2, 0, 1 ], [ 0, 2, -2, -2, 0, 1 ], [ 1, 2, -2, -2, 0, 1 ] ], 0.625 ] - ], - [ - [ [ [ -1, 2, -2, -2, 0, 1 ], [ 1, 1, -2, -2, 0, 1 ], [ 1, 1, -3, -2, 0, 1 ], [ 1, 2, -2, -2, 0, 1 ] ], 0.625 ], - [ [ [ 0, 1, -3, -2, 0, 1 ], [ 1, 1, -2, -2, 0, 1 ], [ 1, 1, -3, -2, 0, 1 ], [ 1, 2, -2, -2, 0, 1 ] ], 1.25 ] - ], - [ - [ [ [ 0, 1, -3, -2, 0, 1 ], [ 1, 0, -3, -2, 0, 1 ], [ 1, 1, -3, -2, 0, 1 ], [ 1, 2, -2, -2, 0, 1 ] ], 1.375 ], - [ [ [ -1, 2, -3, -2, 0, 1 ], [ 1, 0, -3, -2, 0, 1 ], [ 1, 1, -3, -2, 0, 1 ], [ 1, 2, -2, -2, 0, 1 ] ], 0.5 ] - ], - [ - [ [ [ -1, 2, -3, -2, 0, 1 ], [ 0, 2, -3, -2, 0, 1 ], [ 1, 1, -3, -2, 0, 1 ], [ 1, 2, -2, -2, 0, 1 ] ], 1 ], - [ [ [ 0, 1, -4, -2, 0, 1 ], [ 0, 2, -3, -2, 0, 1 ], [ 1, 1, -3, -2, 0, 1 ], [ 1, 2, -2, -2, 0, 1 ] ], 1.5 ] - ], - [ - [ [ [ 0, 1, -4, -2, 0, 1 ], [ 1, 1, -4, -2, 0, 1 ], [ 1, 1, -3, -2, 0, 1 ], [ 1, 2, -2, -2, 0, 1 ] ], 1.75 ], - [ [ [ -2, 3, -2, -2, 0, 1 ], [ 1, 1, -4, -2, 0, 1 ], [ 1, 1, -3, -2, 0, 1 ], [ 1, 2, -2, -2, 0, 1 ] ], 1.625 ] - ], - [ - [ [ [ -2, 2, -2, -2, 0, 2 ], [ 1, 1, -4, -2, 0, 1 ], [ 1, 1, -3, -2, 0, 1 ], [ 1, 2, -2, -2, 0, 1 ] ], 1.25 ], - [ [ [ -2, 2, -2, -2, 0, 2 ], [ 1, 1, -4, -2, 0, 1 ], [ 1, 2, -2, -3, 0, 1 ], [ 1, 2, -2, -2, 0, 1 ] ], 1.25 ], - [ [ [ -2, 2, -2, -2, 0, 2 ], [ -1, 2, -2, -2, 0, 2 ], [ 1, 2, -2, -3, 0, 1 ], [ 1, 2, -2, -2, 0, 1 ] ], 0.5 ] - ], - [ - [ [ [ -2, 2, -2, -2, 0, 2 ], [ 0, 3, -2, -3, 0, 1 ], [ 1, 2, -2, -3, 0, 1 ], [ 1, 2, -2, -2, 0, 1 ] ], 0.625 ], - [ [ [ -1, 3, -2, -3, 0, 1 ], [ 0, 3, -2, -3, 0, 1 ], [ 1, 2, -2, -3, 0, 1 ], [ 1, 2, -2, -2, 0, 1 ] ], 0.625 ] - ], - [ - [ [ [ -1, 3, -2, -3, 0, 1 ], [ 0, 3, -2, -3, 0, 1 ], [ 1, 2, -2, -3, 0, 1 ], [ 2, 2, -2, -3, 0, 1 ] ], 0.75 ] - ], - [ - [ [ [ -1, 3, -2, -3, 0, 1 ], [ 0, 3, -2, -3, 0, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ 2, 2, -2, -3, 0, 1 ] ], 0.75 ], - [ [ [ 0, 3, -2, -4, 0, 1 ], [ 0, 3, -2, -3, 0, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ 2, 2, -2, -3, 0, 1 ] ], 0.875 ] - ], - [ - [ [ [ 0, 3, -2, -4, 0, 1 ], [ 0, 3, -2, -3, 0, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ 1, 4, -2, -3, 0, 1 ] ], 0.875 ] - ], - [ - [ [ [ -1, 3, -1, -3, 0, 1 ], [ 0, 3, -2, -3, 0, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ 1, 4, -2, -3, 0, 1 ] ], 1.25 ] - ], - [ - [ [ [ 0, 2, -2, -3, 0, 1 ], [ 0, 3, -2, -3, 0, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ 1, 4, -2, -3, 0, 1 ] ], 1.25 ] - ], - [ - [ [ [ 0, 2, -2, -3, 0, 1 ], [ 0, 3, -2, -3, 0, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ 1, 3, -1, -3, 0, 1 ] ], 1.125 ], - [ [ [ 0, 3, -2, -3, -1, 1 ], [ 0, 3, -2, -3, 0, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ 1, 3, -1, -3, 0, 1 ] ], 1.25 ] - ], - [ - [ [ [ 0, 3, -2, -3, -1, 1 ], [ 0, 4, -2, -3, -1, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ 1, 3, -1, -3, 0, 1 ] ], 0.875 ], - [ [ [ -1, 3, -2, -3, 0, 1 ], [ 0, 4, -2, -3, -1, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ 1, 3, -1, -3, 0, 1 ] ], 1.625 ], - [ [ [ -1, 3, -2, -3, 0, 1 ], [ 0, 4, -2, -3, -1, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ 0, 4, -2, -2, 0, 1 ] ], 0.375 ] - ], - [ - [ [ [ -1, 3, -2, -3, 0, 1 ], [ 0, 3, -1, -3, 0, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ 0, 4, -2, -2, 0, 1 ] ], 0.5 ], - [ [ [ -1, 3, -2, -3, 0, 1 ], [ 0, 3, -1, -3, 0, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ 1, 4, -2, -3, 0, 1 ] ], 0.5 ] - ], - [ - [ [ [ -1, 4, -2, -3, 0, 0 ], [ 0, 3, -1, -3, 0, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ 1, 4, -2, -3, 0, 1 ] ], 0.75 ], - [ [ [ -1, 4, -2, -3, 0, 0 ], [ -1, 4, -2, -2, 0, 1 ], [ 0, 4, -2, -3, 0, 1 ], [ 1, 4, -2, -3, 0, 1 ] ], 1.5 ] - ], - [ - [ [ [ -1, 4, -2, -3, 0, 0 ], [ -1, 4, -2, -2, 0, 1 ], [ 0, 4, -2, -2, 0, 0 ], [ 1, 4, -2, -3, 0, 1 ] ], 1.125 ], - [ [ [ -1, 4, -2, -3, 0, 0 ], [ -1, 4, -2, -2, 0, 1 ], [ 0, 4, -2, -2, 0, 0 ], [ 2, 3, -2, -3, 0, 0 ] ], 1.5 ] - ], - [ - [ [ [ -1, 3, -2, -2, 0, 0 ], [ -1, 4, -2, -2, 0, 1 ], [ 0, 4, -2, -2, 0, 0 ], [ 2, 3, -2, -3, 0, 0 ] ], 0.625 ], - [ [ [ -1, 3, -2, -2, 0, 0 ], [ 1, 3, -2, -3, 0, 0 ], [ 0, 4, -2, -2, 0, 0 ], [ 2, 3, -2, -3, 0, 0 ] ], 1.125 ], - [ [ [ -1, 3, -2, -2, 0, 0 ], [ 1, 3, -2, -3, 0, 0 ], [ 1, 4, -2, -3, 0, 0 ], [ 2, 3, -2, -3, 0, 0 ] ], 1.625 ] - ], - [ - [ [ [ -1, 3, -2, -2, 0, 0 ], [ 1, 3, -2, -3, 0, 0 ], [ 1, 4, -2, -3, 0, 0 ], [ 1, 5, -2, -3, 0, 0 ] ], 1.125 ] - ], - [ - [ [ [ -1, 3, -2, -2, 0, 0 ], [ 1, 3, -2, -3, 0, 0 ], [ 1, 4, -2, -3, 0, 0 ], [ 3, 3, -2, -3, 0, -1 ] ], 0.75 ], - [ [ [ -1, 3, -2, -2, 0, 0 ], [ 1, 3, -2, -3, 0, 0 ], [ 2, 3, -3, -3, 0, 0 ], [ 3, 3, -2, -3, 0, -1 ] ], 0.5 ], - [ [ [ 0, 3, -2, -3, 0, 0 ], [ 1, 3, -2, -3, 0, 0 ], [ 2, 3, -3, -3, 0, 0 ], [ 3, 3, -2, -3, 0, -1 ] ], 1.25 ] - ], - [ - [ [ [ 0, 3, -2, -3, 0, 0 ], [ 1, 3, -2, -3, 0, 0 ], [ 2, 2, -2, -3, 0, 0 ], [ 3, 3, -2, -3, 0, -1 ] ], 1.5 ] - ], - [ - [ [ [ 0, 3, -2, -3, 0, 0 ], [ 1, 3, -2, -3, 0, 0 ], [ 1, 4, -2, -3, 0, -1 ], [ 3, 3, -2, -3, 0, -1 ] ], 1 ], - [ [ [ 0, 3, -2, -2, 0, -1 ], [ 1, 3, -2, -3, 0, 0 ], [ 1, 4, -2, -3, 0, -1 ], [ 3, 3, -2, -3, 0, -1 ] ], 1.375 ], - [ [ [ 0, 3, -2, -2, 0, -1 ], [ 1, 3, -2, -2, 0, -1 ], [ 1, 4, -2, -3, 0, -1 ], [ 3, 3, -2, -3, 0, -1 ] ], 0.875 ] - ], - [ - [ [ [ 0, 3, -2, -2, 0, -1 ], [ 2, 3, -2, -3, 0, -1 ], [ 1, 4, -2, -3, 0, -1 ], [ 3, 3, -2, -3, 0, -1 ] ], 0.75 ], - [ [ [ 1, 3, -2, -3, 0, -1 ], [ 2, 3, -2, -3, 0, -1 ], [ 1, 4, -2, -3, 0, -1 ], [ 3, 3, -2, -3, 0, -1 ] ], 0.375 ] - ], - [ - [ [ [ 1, 3, -2, -3, 0, -1 ], [ 2, 3, -2, -3, 0, -1 ], [ 2, 3, -3, -3, 0, -1 ], [ 3, 3, -2, -3, 0, -1 ] ], 1.75 ], - [ [ [ 1, 3, -2, -3, 0, -1 ], [ 2, 3, -2, -3, 0, -1 ], [ 2, 3, -3, -3, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ] ], 1.25 ] - ], - [ - [ [ [ 1, 3, -2, -3, 0, -1 ], [ 2, 3, -2, -3, 0, -1 ], [ 3, 3, -3, -4, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ] ], 1.75 ], - [ [ [ 1, 3, -2, -3, 0, -1 ], [ 1, 3, -3, -3, 0, 0 ], [ 3, 3, -3, -4, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ] ], 0.5 ], - [ [ [ 2, 2, -3, -3, 0, -1 ], [ 1, 3, -3, -3, 0, 0 ], [ 3, 3, -3, -4, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ] ], 1.625 ] - ], - [ - [ [ [ 2, 2, -3, -3, 0, -1 ], [ 3, 1, -3, -3, 0, -1 ], [ 3, 3, -3, -4, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ] ], 0.875 ] - ], - [ - [ [ [ 2, 2, -3, -3, 0, -1 ], [ 3, 1, -3, -3, 0, -1 ], [ 3, 3, -3, -4, 0, -1 ], [ 4, 2, -4, -3, 0, -1 ] ], 1.125 ] - ], - [ - [ [ [ 2, 2, -3, -3, 0, -1 ], [ 3, 1, -3, -3, 0, -1 ], [ 3, 3, -3, -4, 0, -1 ], [ 4, 3, -3, -4, 0, -1 ] ], 1.625 ], - [ [ [ 3, 2, -3, -4, 0, -1 ], [ 3, 1, -3, -3, 0, -1 ], [ 3, 3, -3, -4, 0, -1 ], [ 4, 3, -3, -4, 0, -1 ] ], 1.375 ] - ], - [ - [ [ [ 2, 4, -3, -4, 0, -1 ], [ 3, 1, -3, -3, 0, -1 ], [ 3, 3, -3, -4, 0, -1 ], [ 4, 3, -3, -4, 0, -1 ] ], 0.75 ] - ], - [ - [ [ [ 2, 4, -3, -4, 0, -1 ], [ 1, 5, -3, -4, 0, -1 ], [ 3, 3, -3, -4, 0, -1 ], [ 4, 3, -3, -4, 0, -1 ] ], 1.5 ], - [ [ [ 2, 4, -3, -4, 0, -1 ], [ 1, 5, -3, -4, 0, -1 ], [ 3, 3, -3, -4, 0, -1 ], [ 4, 4, -3, -4, -1, -1 ] ], 0.875 ], - [ [ [ 2, 4, -3, -4, 0, -1 ], [ 1, 5, -3, -4, 0, -1 ], [ 3, 4, -3, -4, -1, -1 ], [ 4, 4, -3, -4, -1, -1 ] ], 1.625 ] - ], - [ - [ [ [ 2, 4, -3, -4, 0, -1 ], [ 1, 5, -3, -4, 0, -1 ], [ 3, 4, -4, -4, 0, -1 ], [ 4, 4, -3, -4, -1, -1 ] ], 0.5 ], - [ [ [ 2, 4, -3, -4, 0, -1 ], [ 2, 4, -4, -4, 0, -1 ], [ 3, 4, -4, -4, 0, -1 ], [ 4, 4, -3, -4, -1, -1 ] ], 1.375 ] - ], - [ - [ [ [ 2, 4, -3, -4, 0, -1 ], [ 2, 4, -4, -4, 0, -1 ], [ 3, 4, -4, -4, 0, -1 ], [ 3, 4, -2, -4, 0, -1 ] ], 1.75 ], - [ [ [ 2, 4, -3, -4, 0, -1 ], [ 1, 4, -3, -3, 0, -1 ], [ 3, 4, -4, -4, 0, -1 ], [ 3, 4, -2, -4, 0, -1 ] ], 0.625 ], - [ [ [ 2, 4, -3, -4, 0, -1 ], [ 1, 4, -3, -3, 0, -1 ], [ 2, 4, -3, -3, 0, -1 ], [ 3, 4, -2, -4, 0, -1 ] ], 1.75 ] - ], - [ - [ [ [ 2, 4, -3, -4, 0, -1 ], [ 1, 4, -3, -3, 0, -1 ], [ 2, 4, -3, -3, 0, -1 ], [ 2, 5, -3, -3, 0, -1 ] ], 0.75 ], - [ [ [ 2, 4, -3, -4, 0, -1 ], [ 1, 4, -3, -3, 0, -1 ], [ 3, 4, -3, -4, 0, -1 ], [ 2, 5, -3, -3, 0, -1 ] ], 0.5 ] - ], - [ - [ [ [ 2, 3, -3, -3, 0, -1 ], [ 1, 4, -3, -3, 0, -1 ], [ 3, 4, -3, -4, 0, -1 ], [ 2, 5, -3, -3, 0, -1 ] ], 0.75 ], - [ [ [ 2, 3, -3, -3, 0, -1 ], [ 1, 4, -3, -3, 0, -1 ], [ 2, 4, -2, -3, 0, -1 ], [ 2, 5, -3, -3, 0, -1 ] ], 1.75 ] - ], - [ - [ [ [ 2, 3, -3, -3, 0, -1 ], [ 1, 4, -3, -3, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ], [ 2, 5, -3, -3, 0, -1 ] ], 1 ], - [ [ [ 2, 3, -3, -3, 0, -1 ], [ 2, 3, -4, -3, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ], [ 2, 5, -3, -3, 0, -1 ] ], 1.125 ] - ], - [ - [ [ [ 2, 3, -3, -3, 0, -1 ], [ 2, 3, -4, -3, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ], [ 3, 3, -2, -3, 0, -1 ] ], 1.5 ], - [ [ [ 2, 3, -3, -3, 0, -1 ], [ 2, 2, -3, -3, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ], [ 3, 3, -2, -3, 0, -1 ] ], 1.625 ], - [ [ [ 3, 3, -3, -4, 0, -1 ], [ 2, 2, -3, -3, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ], [ 3, 3, -2, -3, 0, -1 ] ], 0.5 ] - ], - [ - [ [ [ 3, 3, -3, -4, 0, -1 ], [ 3, 2, -3, -4, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ], [ 3, 3, -2, -3, 0, -1 ] ], 0.75 ] - ], - [ - [ [ [ 2, 3, -2, -3, 0, -1 ], [ 3, 2, -3, -4, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ], [ 3, 3, -2, -3, 0, -1 ] ], 0.875 ], - [ [ [ 2, 3, -2, -3, 0, -1 ], [ 3, 2, -3, -4, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ], [ 2, 3, -3, -3, 0, -1 ] ], 1.125 ] - ], - [ - [ [ [ 2, 3, -2, -3, 0, -1 ], [ 2, 3, -4, -3, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ], [ 2, 3, -3, -3, 0, -1 ] ], 0.875 ], - [ [ [ 3, 2, -3, -3, 0, -1 ], [ 2, 3, -4, -3, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ], [ 2, 3, -3, -3, 0, -1 ] ], 0.875 ] - ], - [ - [ [ [ 3, 2, -3, -3, 0, -1 ], [ 2, 3, -4, -3, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ], [ 3, 3, -3, -4, 0, -1 ] ], 1.25 ], - [ [ [ 3, 2, -3, -3, 0, -1 ], [ 1, 3, -3, -2, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ], [ 3, 3, -3, -4, 0, -1 ] ], 1.25 ], - [ [ [ 2, 4, -3, -3, 0, -1 ], [ 1, 3, -3, -2, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ], [ 3, 3, -3, -4, 0, -1 ] ], 1.125 ] - ], - [ - [ [ [ 2, 4, -3, -3, 0, -1 ], [ 1, 3, -3, -2, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ], [ 1, 4, -3, -2, 0, -1 ] ], 0.625 ] - ], - [ - [ [ [ 2, 3, -3, -2, 0, -1 ], [ 1, 3, -3, -2, 0, -1 ], [ 3, 3, -3, -3, 0, -1 ], [ 1, 4, -3, -2, 0, -1 ] ], 1.25 ], - [ [ [ 2, 3, -3, -2, 0, -1 ], [ 1, 3, -3, -2, 0, -1 ], [ 2, 3, -2, -2, 0, -1 ], [ 1, 4, -3, -2, 0, -1 ] ], 1.375 ] - ], - [ - [ [ [ 1, 3, -2, -2, 0, -1 ], [ 1, 3, -3, -2, 0, -1 ], [ 2, 3, -2, -2, 0, -1 ], [ 1, 4, -3, -2, 0, -1 ] ], 0.875 ] - ], - [ - [ [ [ 1, 3, -2, -2, 0, -1 ], [ 1, 3, -3, -2, 0, -1 ], [ 2, 3, -2, -2, 0, -1 ], [ 2, 2, -2, -2, 0, -1 ] ], 1.5 ] - ], - [ - [ [ [ 1, 3, -2, -2, 0, -1 ], [ 2, 1, -2, -2, 0, -1 ], [ 2, 3, -2, -2, 0, -1 ], [ 2, 2, -2, -2, 0, -1 ] ], 0.5 ] - ], - [ - [ [ [ 1, 3, -2, -2, 0, -1 ], [ 2, 1, -2, -2, 0, -1 ], [ 3, 1, -2, -2, 0, -1 ], [ 2, 2, -2, -2, 0, -1 ] ], 1.625 ], - [ [ [ 2, 0, -2, -2, 0, -1 ], [ 2, 1, -2, -2, 0, -1 ], [ 3, 1, -2, -2, 0, -1 ], [ 2, 2, -2, -2, 0, -1 ] ], 1.5 ], - [ [ [ 2, 0, -2, -2, 0, -1 ], [ 2, 1, -2, -2, 0, -1 ], [ 3, 1, -2, -2, 0, -1 ], [ 3, 1, -3, -2, 0, -1 ] ], 0.75 ] - ], - [ - [ [ [ 2, 0, -2, -2, 0, -1 ], [ 3, 0, -3, -2, 0, -1 ], [ 3, 1, -2, -2, 0, -1 ], [ 3, 1, -3, -2, 0, -1 ] ], 1.5 ] - ], - [ - [ [ [ 2, 0, -2, -2, 0, -1 ], [ 3, 0, -3, -2, 0, -1 ], [ 4, 0, -3, -2, 0, -1 ], [ 3, 1, -3, -2, 0, -1 ] ], 1 ], - [ [ [ 2, 0, -3, -2, 0, -1 ], [ 3, 0, -3, -2, 0, -1 ], [ 4, 0, -3, -2, 0, -1 ], [ 3, 1, -3, -2, 0, -1 ] ], 1.25 ], - [ [ [ 2, 0, -3, -2, 0, -1 ], [ 3, 0, -3, -2, 0, -1 ], [ 4, 0, -3, -2, 0, -1 ], [ 4, 0, -4, -2, 0, -1 ] ], 1.25 ] - ], - [ - [ [ [ 2, 0, -3, -2, 0, -1 ], [ 2, 0, -4, -2, 0, 0 ], [ 4, 0, -3, -2, 0, -1 ], [ 4, 0, -4, -2, 0, -1 ] ], 0.5 ], - [ [ [ 3, -1, -4, -2, 0, -1 ], [ 2, 0, -4, -2, 0, 0 ], [ 4, 0, -3, -2, 0, -1 ], [ 4, 0, -4, -2, 0, -1 ] ], 1.125 ], - [ [ [ 3, -1, -4, -2, 0, -1 ], [ 2, 0, -4, -2, 0, 0 ], [ 5, -1, -4, -2, 0, -1 ], [ 4, 0, -4, -2, 0, -1 ] ], 0.5 ] - ], - [ - [ [ [ 3, -1, -4, -2, 0, -1 ], [ 2, 0, -4, -2, 0, 0 ], [ 5, -1, -4, -2, 0, -1 ], [ 4, -1, -4, -2, 0, 0 ] ], 1.75 ] - ], - [ - [ [ [ 2, 0, -4, -2, 0, -1 ], [ 2, 0, -4, -2, 0, 0 ], [ 5, -1, -4, -2, 0, -1 ], [ 4, -1, -4, -2, 0, 0 ] ], 0.5 ], - [ [ [ 2, 0, -4, -2, 0, -1 ], [ 2, 0, -4, -2, 0, 0 ], [ 5, -1, -4, -2, 0, -1 ], [ 3, 1, -4, -2, 0, 0 ] ], 1.125 ], - [ [ [ 2, 0, -4, -2, 0, -1 ], [ 2, 0, -4, -2, 0, 0 ], [ 3, 0, -4, -1, 0, 0 ], [ 3, 1, -4, -2, 0, 0 ] ], 0.5 ] - ], - [ - [ [ [ 2, -1, -4, -2, 0, 0 ], [ 2, 0, -4, -2, 0, 0 ], [ 3, 0, -4, -1, 0, 0 ], [ 3, 1, -4, -2, 0, 0 ] ], 1.625 ], - [ [ [ 2, -1, -4, -2, 0, 0 ], [ 2, 0, -4, -2, 0, 0 ], [ 4, 1, -4, -2, 0, -1 ], [ 3, 1, -4, -2, 0, 0 ] ], 0.75 ] - ], - [ - [ [ [ 2, -1, -4, -2, 0, 0 ], [ 2, 0, -4, -2, 0, 0 ], [ 4, 0, -5, -2, 0, 0 ], [ 3, 1, -4, -2, 0, 0 ] ], 1.75 ], - [ [ [ 2, -1, -4, -2, 0, 0 ], [ 2, 0, -4, -2, 0, 0 ], [ 4, 0, -5, -2, 0, 0 ], [ 4, -1, -4, -2, 0, -1 ] ], 0.5 ] - ], - [ - [ [ [ 2, -1, -4, -2, 0, 0 ], [ 2, 0, -4, -2, 0, 0 ], [ 4, 0, -5, -2, 0, 0 ], [ 2, 0, -4, -1, 0, 0 ] ], 1.75 ] - ], - [ - [ [ [ 1, 1, -4, -2, 0, 0 ], [ 2, 0, -4, -2, 0, 0 ], [ 4, 0, -5, -2, 0, 0 ], [ 2, 0, -4, -1, 0, 0 ] ], 0.875 ], - [ [ [ 1, 1, -4, -2, 0, 0 ], [ 2, 0, -4, -2, 0, 0 ], [ 3, 0, -4, -1, 0, 0 ], [ 2, 0, -4, -1, 0, 0 ] ], 0.875 ] - ], - [ - [ [ [ 1, 1, -4, -2, 0, 0 ], [ 2, 0, -4, -2, 0, 0 ], [ 4, 1, -4, -2, 0, -1 ], [ 2, 0, -4, -1, 0, 0 ] ], 1.625 ] - ], - [ - [ [ [ 1, 1, -4, -2, 0, 0 ], [ 1, 2, -4, -2, 0, 0 ], [ 4, 1, -4, -2, 0, -1 ], [ 2, 0, -4, -1, 0, 0 ] ], 0.5 ], - [ [ [ 1, 1, -4, -2, 0, 0 ], [ 1, 2, -4, -2, 0, 0 ], [ 3, 1, -4, -2, 0, 0 ], [ 2, 0, -4, -1, 0, 0 ] ], 0.875 ], - [ [ [ 1, 1, -4, -2, 0, 0 ], [ 1, 2, -4, -2, 0, 0 ], [ 3, 1, -4, -2, 0, 0 ], [ 2, 1, -4, -2, 0, 0 ] ], 1.125 ] - ], - [ - [ [ [ 0, 2, -4, -2, 0, 0 ], [ 1, 2, -4, -2, 0, 0 ], [ 3, 1, -4, -2, 0, 0 ], [ 2, 1, -4, -2, 0, 0 ] ], 1.625 ] - ], - [ - [ [ [ 0, 2, -4, -2, 0, 0 ], [ 1, 2, -4, -2, 0, 0 ], [ 3, 1, -4, -2, 0, 0 ], [ 1, 3, -4, -2, 0, 0 ] ], 0.75 ] - ], - [ - [ [ [ 1, 2, -4, -3, 0, 0 ], [ 1, 2, -4, -2, 0, 0 ], [ 3, 1, -4, -2, 0, 0 ], [ 1, 3, -4, -2, 0, 0 ] ], 0.875 ] - ], - [ - [ [ [ 1, 2, -4, -3, 0, 0 ], [ 1, 2, -4, -2, 0, 0 ], [ 3, 1, -4, -2, 0, 0 ], [ 3, 1, -4, -2, 0, -1 ] ], 1.5 ], - [ [ [ 1, 2, -4, -3, 0, 0 ], [ 2, 2, -4, -3, 0, 0 ], [ 3, 1, -4, -2, 0, 0 ], [ 3, 1, -4, -2, 0, -1 ] ], 1.5 ] - ], - [ - [ [ [ 1, 2, -4, -3, 0, 0 ], [ 2, 2, -4, -3, 0, 0 ], [ 3, 1, -4, -2, 0, 0 ], [ 3, 0, -4, -2, 0, 0 ] ], 0.5 ], - [ [ [ 1, 1, -4, -2, 0, 0 ], [ 2, 2, -4, -3, 0, 0 ], [ 3, 1, -4, -2, 0, 0 ], [ 3, 0, -4, -2, 0, 0 ] ], 0.5 ], - [ [ [ 1, 1, -4, -2, 0, 0 ], [ 2, 1, -4, -2, 0, 0 ], [ 3, 1, -4, -2, 0, 0 ], [ 3, 0, -4, -2, 0, 0 ] ], 0.5 ] - ], - [ - [ [ [ 1, 1, -4, -2, 0, 0 ], [ 2, 1, -4, -2, 0, 0 ], [ 4, 0, -5, -2, 0, 0 ], [ 3, 0, -4, -2, 0, 0 ] ], 1.375 ], - [ [ [ 2, 0, -5, -2, 0, 0 ], [ 2, 1, -4, -2, 0, 0 ], [ 4, 0, -5, -2, 0, 0 ], [ 3, 0, -4, -2, 0, 0 ] ], 0.875 ], - [ [ [ 2, 0, -5, -2, 0, 0 ], [ 3, 0, -5, -2, 0, 0 ], [ 4, 0, -5, -2, 0, 0 ], [ 3, 0, -4, -2, 0, 0 ] ], 0.625 ] - ], - [ - [ [ [ 1, 0, -4, -2, 0, 0 ], [ 3, 0, -5, -2, 0, 0 ], [ 4, 0, -5, -2, 0, 0 ], [ 3, 0, -4, -2, 0, 0 ] ], 0.625 ], - [ [ [ 1, 0, -4, -2, 0, 0 ], [ 2, 0, -4, -2, 0, 0 ], [ 4, 0, -5, -2, 0, 0 ], [ 3, 0, -4, -2, 0, 0 ] ], 1.375 ], - [ [ [ 1, 0, -4, -2, 0, 0 ], [ 2, 0, -4, -2, 0, 0 ], [ 3, 1, -4, -2, 0, 0 ], [ 3, 0, -4, -2, 0, 0 ] ], 1.125 ] - ], - [ - [ [ [ 1, 0, -4, -2, 0, 0 ], [ 2, 0, -4, -2, 0, 0 ], [ 2, 1, -4, -2, 0, 0 ], [ 3, 0, -4, -2, 0, 0 ] ], 1.625 ], - [ [ [ 1, 0, -4, -2, 0, 0 ], [ 2, 0, -4, -2, 0, 0 ], [ 2, 1, -4, -2, 0, 0 ], [ 4, 0, -4, -3, 0, 0 ] ], 1.25 ] - ], - [ - [ [ [ 1, 0, -4, -2, 0, 0 ], [ 2, 0, -4, -2, 0, 0 ], [ 3, 0, -5, -2, 0, 0 ], [ 4, 0, -4, -3, 0, 0 ] ], 0.75 ], - [ [ [ 1, 0, -4, -2, 0, 0 ], [ 2, 0, -4, -2, 0, 0 ], [ 3, 0, -5, -2, 0, 0 ], [ 2, 1, -4, -2, 0, 0 ] ], 1.375 ] - ], - [ - [ [ [ 1, 0, -4, -2, 0, 0 ], [ 2, 0, -5, -2, 1, 0 ], [ 3, 0, -5, -2, 0, 0 ], [ 2, 1, -4, -2, 0, 0 ] ], 1.625 ], - [ [ [ 1, 0, -4, -2, 0, 0 ], [ 2, 0, -5, -2, 1, 0 ], [ 3, 0, -5, -2, 0, 0 ], [ 2, 0, -4, -1, 0, 0 ] ], 0.75 ] - ], - [ - [ [ [ 1, 0, -5, -2, 1, 0 ], [ 2, 0, -5, -2, 1, 0 ], [ 3, 0, -5, -2, 0, 0 ], [ 2, 0, -4, -1, 0, 0 ] ], 1.375 ], - [ [ [ 1, 0, -5, -2, 1, 0 ], [ 3, 0, -5, -2, -1, 0 ], [ 3, 0, -5, -2, 0, 0 ], [ 2, 0, -4, -1, 0, 0 ] ], 1.75 ], - [ [ [ 1, 0, -5, -2, 1, 0 ], [ 3, 0, -5, -2, -1, 0 ], [ 3, 0, -5, -2, 0, 0 ], [ 4, 0, -5, -2, 0, -1 ] ], 1.25 ] - ], - [ - [ [ [ 1, 0, -5, -2, 1, 0 ], [ 3, 0, -5, -2, -1, 0 ], [ 3, 0, -6, -2, 1, 0 ], [ 4, 0, -5, -2, 0, -1 ] ], 1.375 ], - [ [ [ 1, 0, -5, -2, 1, 0 ], [ 3, 0, -5, -2, -1, 0 ], [ 3, 0, -6, -2, 1, 0 ], [ "Rest" ] ], 0.625 ], - [ [ [ 1, 0, -5, -2, 1, 0 ], [ 3, 0, -5, -2, -1, 0 ], [ "Rest" ], [ "Rest" ] ], 0.875 ], - [ [ [ 1, 0, -5, -2, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.375 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 6.75 ] - ] - ] -], -"last_changes": -[ - [ [ 1, 0, -4, -2, 0, 0 ], [ 2, 0, -5, -2, 1, 0 ], [ 3, 0, -5, -2, 0, 0 ], [ 2, 0, -4, -1, 0, 0 ] ], - [ [ 1, 0, -5, -2, 1, 0 ], [ 2, 0, -5, -2, 1, 0 ], [ 3, 0, -5, -2, 0, 0 ], [ 2, 0, -4, -1, 0, 0 ] ], - [ [ 1, 0, -5, -2, 1, 0 ], [ 3, 0, -5, -2, -1, 0 ], [ 3, 0, -5, -2, 0, 0 ], [ 2, 0, -4, -1, 0, 0 ] ], - [ [ 1, 0, -5, -2, 1, 0 ], [ 3, 0, -5, -2, -1, 0 ], [ 3, 0, -5, -2, 0, 0 ], [ 4, 0, -5, -2, 0, -1 ] ], - [ [ 1, 0, -5, -2, 1, 0 ], [ 3, 0, -5, -2, -1, 0 ], [ 3, 0, -6, -2, 1, 0 ], [ 4, 0, -5, -2, 0, -1 ] ] -], -"cur_uid": "69c568c6", -"ref_uid": "nil", -"order_seed": 712406, -"dur_seed": 506999, -"motifs_seed": 551883, -"entrances_probs_vals": [ 0, 0, 0, 0.41, 1.84, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 0.41, 1.84, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 3.2936507936508, 0.41, 1.84, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ -1200, 1200, 0.0020576131687243, 0.068181818181818, 0.074074074074074, 0.0625, 0.20576131687243, 0.0625, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61316872427983, 0, 0.98971193415638, 0 ], -"passages_weights": [ 0.48, 0.46, 0.48, 1, 1 ], -"hd_exp": 9, -"hd_invert": 0, -"order": -[ - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 0, 3 ], [ 1, 2 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 0, 2 ], [ 1, 3 ], [ ] ], - [ [ 1 ], [ 0, 2, 3 ], [ ] ], - [ [ 1, 3 ], [ 2, 0 ], [ ] ], - [ [ 3 ], [ 1, 0, 2 ], [ ] ], - [ [ 3, 1 ], [ 2, 0 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 0, 3 ], [ 2, 1 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 3, 0 ], [ 1, 2 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 0, 1 ], [ 2, 3 ], [ ] ], - [ [ 3, 0 ], [ 1, 2 ], [ ] ], - [ [ 0, 3 ], [ 1, 2 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0, 1 ], [ 2, 3 ], [ ] ], - [ [ 2 ], [ 3, 1, 0 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 3 ], [ 0, 1, 2 ], [ ] ], - [ [ 0, 1 ], [ 2, 3 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 1, 3 ], [ 2, 0 ], [ ] ], - [ [ 1 ], [ 0, 3, 2 ], [ ] ], - [ [ 3, 1 ], [ 2, 0 ], [ ] ], - [ [ 2, 3 ], [ 1, 0 ], [ ] ], - [ [ 3, 2 ], [ 1, 0 ], [ ] ], - [ [ 2, 3 ], [ 1, 0 ], [ ] ], - [ [ 3 ], [ 0, 2, 1 ], [ ] ], - [ [ 2, 3 ], [ 1, 0 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 3, 1 ], [ 2, 0 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 2, 0 ], [ 1, 3 ], [ ] ], - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 0, 1 ], [ 2, 3 ], [ ] ], - [ [ 3 ], [ 0, 1, 2 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 1 ], [ 3, 2, 0 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 3 ], [ 2, 0, 1 ], [ ] ], - [ [ 3, 2 ], [ 1, 0 ], [ ] ], - [ [ 0, 1 ], [ 2, 3 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 3, 0 ], [ 2, 1 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 1, 0 ], [ 3, 2 ], [ ] ], - [ [ 1, 3 ], [ 0, 2 ], [ ] ], - [ [ 3, 0 ], [ 2, 1 ], [ ] ], - [ [ 2 ], [ 3, 1, 0 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 1, 2 ], [ 0, 3 ], [ ] ], - [ [ 3, 2 ], [ 1, 0 ], [ ] ], - [ [ 2 ], [ 3, 1, 0 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 2, 0, 3 ], [ 1 ], [ ] ], - [ [ 1 ], [ 2, 0, 3 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 1 ], [ 2, 0, 3 ], [ ] ], - [ [ 3 ], [ 1, 0, 2 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 1 ], [ 0, 3, 2 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 1, 0 ], [ 2, 3 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 0 ], [ 1, 2, 3 ], [ ] ], - [ [ 1, 3, 2 ], [ 0 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 2, 0 ], [ 3, 1 ], [ ] ], - [ [ 2 ], [ 3, 0, 1 ], [ ] ], - [ [ 3 ], [ 2, 0, 1 ], [ ] ], - [ [ 3 ], [ 0, 1, 2 ], [ ] ], - [ [ 0, 1 ], [ 2, 3 ], [ ] ], - [ [ 1, 0 ], [ 2, 3 ], [ ] ], - [ [ 0, 2 ], [ 1, 3 ], [ ] ], - [ [ 2 ], [ 0, 1, 3 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 100, 100 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/6a9928d6/6a9928d6_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3/6a9928d6/6a9928d6_code.scd deleted file mode 100644 index 49436ca..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/6a9928d6/6a9928d6_code.scd +++ /dev/null @@ -1,973 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - - - //isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/6a9928d6/6a9928d6_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3/6a9928d6/6a9928d6_mus_model.json deleted file mode 100644 index 7ef872c..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/6a9928d6/6a9928d6_mus_model.json +++ /dev/null @@ -1,554 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 2, -4, 0, 3, -1, 0 ], [ "Rest" ] ], 1.5 ], - [ [ [ "Rest" ], [ "Rest" ], [ 2, -4, 0, 3, -1, 0 ], [ 4, -5, -1, 2, -1, -1 ] ], 0.5 ], - [ [ [ "Rest" ], [ 2, -5, 0, 3, -1, -1 ], [ 2, -4, 0, 3, -1, 0 ], [ 4, -5, -1, 2, -1, -1 ] ], 1.75 ], - [ [ [ 1, -5, 0, 3, -1, -1 ], [ 2, -5, 0, 3, -1, -1 ], [ 2, -4, 0, 3, -1, 0 ], [ 4, -5, -1, 2, -1, -1 ] ], 0.875 ] - ], - [ - [ [ [ 1, -5, 0, 3, -1, -1 ], [ 4, -5, -1, 2, -1, -2 ], [ 2, -4, 0, 3, -1, 0 ], [ 4, -5, -1, 2, -1, -1 ] ], 1.125 ], - [ [ [ 1, -5, 0, 3, -1, -1 ], [ 4, -5, -1, 2, -1, -2 ], [ 4, -5, -2, 2, -1, -1 ], [ 4, -5, -1, 2, -1, -1 ] ], 1.625 ], - [ [ [ 2, -5, 0, 2, -1, -1 ], [ 4, -5, -1, 2, -1, -2 ], [ 4, -5, -2, 2, -1, -1 ], [ 4, -5, -1, 2, -1, -1 ] ], 1.875 ] - ], - [ - [ [ [ 2, -5, 0, 2, -1, -1 ], [ 4, -5, -1, 2, -1, -2 ], [ 3, -5, 0, 2, 0, -1 ], [ 4, -5, -1, 2, -1, -1 ] ], 1.125 ], - [ [ [ 2, -5, 0, 2, -1, -1 ], [ 4, -5, -1, 2, -1, -2 ], [ 3, -5, 0, 2, 0, -1 ], [ 4, -6, 0, 2, -1, -1 ] ], 0.5 ], - [ [ [ 2, -5, 0, 2, -1, -1 ], [ 3, -6, 0, 2, -1, -1 ], [ 3, -5, 0, 2, 0, -1 ], [ 4, -6, 0, 2, -1, -1 ] ], 1.875 ] - ], - [ - [ [ [ 2, -5, 0, 2, -1, -1 ], [ 2, -5, 0, 2, 0, -2 ], [ 3, -5, 0, 2, 0, -1 ], [ 4, -6, 0, 2, -1, -1 ] ], 0.75 ], - [ [ [ 1, -5, 0, 2, 0, 0 ], [ 2, -5, 0, 2, 0, -2 ], [ 3, -5, 0, 2, 0, -1 ], [ 4, -6, 0, 2, -1, -1 ] ], 0.5 ], - [ [ [ 1, -5, 0, 2, 0, 0 ], [ 2, -5, 0, 2, 0, -2 ], [ 3, -5, 0, 2, 0, -1 ], [ 3, -5, -1, 2, 0, -1 ] ], 0.75 ] - ], - [ - [ [ [ 1, -5, 0, 2, 0, 0 ], [ 2, -5, 0, 2, 0, -2 ], [ 3, -5, 0, 2, 1, -2 ], [ 3, -5, -1, 2, 0, -1 ] ], 1.625 ], - [ [ [ 3, -5, 0, 1, 0, -2 ], [ 2, -5, 0, 2, 0, -2 ], [ 3, -5, 0, 2, 1, -2 ], [ 3, -5, -1, 2, 0, -1 ] ], 1.625 ] - ], - [ - [ [ [ 3, -5, 0, 2, 0, -3 ], [ 2, -5, 0, 2, 0, -2 ], [ 3, -5, 0, 2, 1, -2 ], [ 3, -5, -1, 2, 0, -1 ] ], 1.875 ] - ], - [ - [ [ [ 3, -5, 0, 2, 0, -3 ], [ 2, -5, 0, 2, 0, -2 ], [ 4, -5, 1, 2, 0, -3 ], [ 3, -5, -1, 2, 0, -1 ] ], 0.625 ], - [ [ [ 3, -5, 0, 2, 0, -3 ], [ 2, -5, 0, 3, 0, -3 ], [ 4, -5, 1, 2, 0, -3 ], [ 3, -5, -1, 2, 0, -1 ] ], 1.125 ], - [ [ [ 3, -5, 0, 2, 0, -3 ], [ 2, -5, 0, 3, 0, -3 ], [ 4, -5, 1, 2, 0, -3 ], [ 5, -5, 0, 1, 0, -3 ] ], 1.625 ] - ], - [ - [ [ [ 3, -5, 0, 2, 0, -3 ], [ 4, -5, -1, 2, 0, -3 ], [ 4, -5, 1, 2, 0, -3 ], [ 5, -5, 0, 1, 0, -3 ] ], 1 ], - [ [ [ 3, -5, 0, 2, 0, -3 ], [ 4, -5, -1, 2, 0, -3 ], [ 4, -5, 1, 2, 0, -3 ], [ 5, -5, 0, 2, 0, -4 ] ], 0.5 ], - [ [ [ 3, -5, 0, 2, 0, -3 ], [ 4, -5, -1, 2, 0, -3 ], [ 4, -5, 0, 2, 1, -3 ], [ 5, -5, 0, 2, 0, -4 ] ], 1.5 ] - ], - [ - [ [ [ 3, -5, 0, 3, 0, -4 ], [ 4, -5, -1, 2, 0, -3 ], [ 4, -5, 0, 2, 1, -3 ], [ 5, -5, 0, 2, 0, -4 ] ], 0.5 ] - ], - [ - [ [ [ 3, -5, 0, 2, 1, -4 ], [ 4, -5, -1, 2, 0, -3 ], [ 4, -5, 0, 2, 1, -3 ], [ 5, -5, 0, 2, 0, -4 ] ], 1.875 ], - [ [ [ 3, -5, 0, 2, 1, -4 ], [ 4, -5, 0, 2, 1, -4 ], [ 4, -5, 0, 2, 1, -3 ], [ 5, -5, 0, 2, 0, -4 ] ], 1.75 ], - [ [ [ 3, -5, 0, 2, 1, -4 ], [ 4, -5, 0, 2, 1, -4 ], [ 4, -5, 0, 2, 1, -3 ], [ 3, -4, 0, 2, 1, -3 ] ], 0.5 ] - ], - [ - [ [ [ 3, -5, 0, 2, 1, -4 ], [ 4, -5, 0, 2, 1, -4 ], [ 4, -5, 0, 2, 1, -3 ], [ 3, -5, 0, 2, 1, -2 ] ], 1.5 ] - ], - [ - [ [ [ 3, -5, 0, 2, 1, -4 ], [ 4, -5, 0, 2, 1, -4 ], [ 4, -5, 0, 2, 2, -4 ], [ 3, -5, 0, 2, 1, -2 ] ], 1.25 ] - ], - [ - [ [ [ 2, -5, -1, 2, 1, -2 ], [ 4, -5, 0, 2, 1, -4 ], [ 4, -5, 0, 2, 2, -4 ], [ 3, -5, 0, 2, 1, -2 ] ], 1.375 ], - [ [ [ 2, -5, -1, 2, 1, -2 ], [ 4, -5, 0, 2, 1, -4 ], [ 4, -5, 0, 1, 1, -2 ], [ 3, -5, 0, 2, 1, -2 ] ], 0.875 ], - [ [ [ 2, -5, -1, 2, 1, -2 ], [ 2, -5, 0, 3, 1, -2 ], [ 4, -5, 0, 1, 1, -2 ], [ 3, -5, 0, 2, 1, -2 ] ], 1.875 ] - ], - [ - [ [ [ 2, -5, -1, 2, 1, -2 ], [ 4, -5, -1, 2, 1, -3 ], [ 4, -5, 0, 1, 1, -2 ], [ 3, -5, 0, 2, 1, -2 ] ], 0.875 ], - [ [ [ 2, -5, -1, 2, 1, -2 ], [ 4, -5, -1, 2, 1, -3 ], [ 4, -5, 0, 1, 1, -2 ], [ 4, -6, -1, 2, 1, -2 ] ], 1.75 ], - [ [ [ 2, -5, -1, 2, 1, -2 ], [ 4, -5, -1, 2, 1, -3 ], [ 3, -4, -1, 2, 1, -2 ], [ 4, -6, -1, 2, 1, -2 ] ], 0.875 ] - ], - [ - [ [ [ 2, -5, -1, 2, 1, -2 ], [ 4, -5, -1, 2, 1, -3 ], [ 3, -4, -1, 2, 1, -2 ], [ 5, -5, -1, 1, 1, -3 ] ], 1.125 ], - [ [ [ 2, -5, -1, 2, 1, -2 ], [ 4, -5, -1, 2, 1, -3 ], [ 4, -6, -1, 2, 1, -2 ], [ 5, -5, -1, 1, 1, -3 ] ], 1 ] - ], - [ - [ [ [ 2, -5, -1, 2, 1, -2 ], [ 4, -5, -1, 2, 1, -3 ], [ 4, -6, -1, 2, 1, -2 ], [ 3, -6, -1, 3, 1, -2 ] ], 0.625 ], - [ [ [ 3, -6, -2, 2, 1, -2 ], [ 4, -5, -1, 2, 1, -3 ], [ 4, -6, -1, 2, 1, -2 ], [ 3, -6, -1, 3, 1, -2 ] ], 0.75 ], - [ [ [ 3, -6, -2, 2, 1, -2 ], [ 2, -6, -1, 2, 1, -1 ], [ 4, -6, -1, 2, 1, -2 ], [ 3, -6, -1, 3, 1, -2 ] ], 0.5 ] - ], - [ - [ [ [ 3, -6, -2, 2, 1, -2 ], [ 4, -6, -2, 1, 1, -2 ], [ 4, -6, -1, 2, 1, -2 ], [ 3, -6, -1, 3, 1, -2 ] ], 1.5 ], - [ [ [ 3, -6, -2, 2, 1, -2 ], [ 4, -6, -2, 1, 1, -2 ], [ 4, -6, -1, 2, 1, -2 ], [ 5, -6, -2, 2, 1, -3 ] ], 0.75 ], - [ [ [ 3, -6, -2, 2, 1, -2 ], [ 4, -6, -2, 1, 1, -2 ], [ 5, -7, -2, 2, 1, -2 ], [ 5, -6, -2, 2, 1, -3 ] ], 0.875 ] - ], - [ - [ [ [ 3, -6, -2, 2, 1, -2 ], [ 4, -6, -2, 2, 1, -3 ], [ 5, -7, -2, 2, 1, -2 ], [ 5, -6, -2, 2, 1, -3 ] ], 1 ], - [ [ [ 3, -6, -2, 2, 1, -2 ], [ 4, -6, -2, 2, 1, -3 ], [ 5, -7, -2, 2, 1, -2 ], [ 4, -6, -2, 2, 2, -2 ] ], 0.5 ], - [ [ [ 3, -6, -2, 2, 1, -2 ], [ 4, -6, -2, 2, 1, -3 ], [ 5, -6, -2, 2, 0, -2 ], [ 4, -6, -2, 2, 2, -2 ] ], 1.125 ] - ], - [ - [ [ [ 3, -6, -2, 2, 1, -2 ], [ 3, -6, -2, 2, 2, -2 ], [ 5, -6, -2, 2, 0, -2 ], [ 4, -6, -2, 2, 2, -2 ] ], 1.75 ], - [ [ [ 3, -6, -2, 2, 1, -2 ], [ 3, -6, -2, 2, 2, -2 ], [ 5, -6, -2, 2, 0, -2 ], [ 5, -6, -2, 1, 1, -2 ] ], 0.5 ], - [ [ [ 3, -6, -2, 2, 1, -2 ], [ 3, -6, -2, 2, 2, -2 ], [ 4, -6, -2, 2, 2, -2 ], [ 5, -6, -2, 1, 1, -2 ] ], 1.75 ] - ], - [ - [ [ [ 3, -6, -2, 2, 1, -2 ], [ 5, -7, -2, 1, 1, -2 ], [ 4, -6, -2, 2, 2, -2 ], [ 5, -6, -2, 1, 1, -2 ] ], 0.875 ] - ], - [ - [ [ [ 3, -6, -2, 2, 1, -2 ], [ 5, -7, -2, 1, 1, -2 ], [ 6, -7, -2, 1, 0, -2 ], [ 5, -6, -2, 1, 1, -2 ] ], 1.25 ] - ], - [ - [ [ [ 3, -6, -2, 2, 1, -2 ], [ 5, -7, -2, 1, 1, -2 ], [ 6, -7, -3, 1, 1, -2 ], [ 5, -6, -2, 1, 1, -2 ] ], 1.625 ], - [ [ [ 3, -6, -2, 2, 1, -2 ], [ 5, -7, -2, 1, 1, -2 ], [ 6, -7, -3, 1, 1, -2 ], [ 5, -7, -2, 1, 1, -1 ] ], 1.375 ], - [ [ [ 5, -7, -2, 1, 0, -2 ], [ 5, -7, -2, 1, 1, -2 ], [ 6, -7, -3, 1, 1, -2 ], [ 5, -7, -2, 1, 1, -1 ] ], 1.375 ] - ], - [ - [ [ [ 5, -7, -2, 1, 0, -2 ], [ 5, -7, -2, 1, 1, -2 ], [ 7, -7, -2, 1, 0, -3 ], [ 5, -7, -2, 1, 1, -1 ] ], 1.5 ], - [ [ [ 5, -7, -2, 1, 0, -2 ], [ 5, -6, -2, 1, 0, -2 ], [ 7, -7, -2, 1, 0, -3 ], [ 5, -7, -2, 1, 1, -1 ] ], 0.875 ] - ], - [ - [ [ [ 5, -7, -2, 1, 0, -2 ], [ 5, -6, -2, 1, 0, -2 ], [ 7, -7, -2, 1, 0, -3 ], [ 5, -6, -2, 1, 0, -1 ] ], 0.75 ], - [ [ [ 6, -8, -2, 1, 0, -3 ], [ 5, -6, -2, 1, 0, -2 ], [ 7, -7, -2, 1, 0, -3 ], [ 5, -6, -2, 1, 0, -1 ] ], 1.75 ] - ], - [ - [ [ [ 6, -8, -2, 1, 0, -3 ], [ 5, -6, -2, 1, 0, -2 ], [ 5, -6, -2, 2, 0, -2 ], [ 5, -6, -2, 1, 0, -1 ] ], 0.5 ] - ], - [ - [ [ [ 6, -8, -2, 1, 0, -3 ], [ 5, -6, -2, 1, 0, -2 ], [ 5, -6, -2, 2, 0, -2 ], [ 6, -6, -2, 1, -1, -2 ] ], 1.375 ], - [ [ [ 6, -8, -2, 1, 0, -3 ], [ 5, -6, -2, 1, 0, -2 ], [ 6, -6, -3, 1, 0, -2 ], [ 6, -6, -2, 1, -1, -2 ] ], 1.25 ] - ], - [ - [ [ [ 5, -6, -3, 1, -1, -2 ], [ 5, -6, -2, 1, 0, -2 ], [ 6, -6, -3, 1, 0, -2 ], [ 6, -6, -2, 1, -1, -2 ] ], 1.75 ], - [ [ [ 5, -6, -3, 1, -1, -2 ], [ 5, -5, -2, 1, -1, -2 ], [ 6, -6, -3, 1, 0, -2 ], [ 6, -6, -2, 1, -1, -2 ] ], 1.375 ], - [ [ [ 5, -6, -3, 1, -1, -2 ], [ 5, -5, -2, 1, -1, -2 ], [ 4, -5, -2, 1, -1, -2 ], [ 6, -6, -2, 1, -1, -2 ] ], 1.25 ] - ], - [ - [ [ [ 5, -6, -3, 1, -1, -2 ], [ 6, -6, -3, 1, -1, -2 ], [ 4, -5, -2, 1, -1, -2 ], [ 6, -6, -2, 1, -1, -2 ] ], 1.375 ], - [ [ [ 4, -6, -2, 2, -1, -2 ], [ 6, -6, -3, 1, -1, -2 ], [ 4, -5, -2, 1, -1, -2 ], [ 6, -6, -2, 1, -1, -2 ] ], 1.125 ], - [ [ [ 4, -6, -2, 2, -1, -2 ], [ 6, -6, -3, 1, -1, -2 ], [ 4, -6, -2, 1, -1, -1 ], [ 6, -6, -2, 1, -1, -2 ] ], 1.75 ] - ], - [ - [ [ [ 4, -6, -2, 2, -1, -2 ], [ 5, -6, -2, 2, -1, -3 ], [ 4, -6, -2, 1, -1, -1 ], [ 6, -6, -2, 1, -1, -2 ] ], 1.625 ], - [ [ [ 4, -6, -2, 2, -1, -2 ], [ 5, -6, -2, 2, -1, -3 ], [ 4, -6, -2, 1, -1, -1 ], [ 5, -6, -1, 2, -1, -2 ] ], 0.875 ], - [ [ [ 4, -6, -2, 2, -1, -2 ], [ 5, -6, -2, 2, -1, -3 ], [ 3, -6, -2, 3, -1, -2 ], [ 5, -6, -1, 2, -1, -2 ] ], 1.625 ] - ], - [ - [ [ [ 4, -6, -2, 2, -1, -2 ], [ 5, -6, -2, 2, -1, -3 ], [ 3, -5, -1, 2, -1, -2 ], [ 5, -6, -1, 2, -1, -2 ] ], 0.875 ], - [ [ [ 3, -6, -1, 3, -1, -2 ], [ 5, -6, -2, 2, -1, -3 ], [ 3, -5, -1, 2, -1, -2 ], [ 5, -6, -1, 2, -1, -2 ] ], 1.375 ] - ], - [ - [ [ [ 3, -6, -1, 3, -1, -2 ], [ 4, -6, 0, 2, -1, -2 ], [ 3, -5, -1, 2, -1, -2 ], [ 5, -6, -1, 2, -1, -2 ] ], 1.25 ], - [ [ [ 3, -6, -1, 3, -1, -2 ], [ 4, -6, 0, 2, -1, -2 ], [ 4, -6, -2, 2, -1, -2 ], [ 5, -6, -1, 2, -1, -2 ] ], 1.25 ], - [ [ [ 3, -5, -1, 2, -1, -2 ], [ 4, -6, 0, 2, -1, -2 ], [ 4, -6, -2, 2, -1, -2 ], [ 5, -6, -1, 2, -1, -2 ] ], 1.25 ] - ], - [ - [ [ [ 3, -5, -1, 2, -1, -2 ], [ 4, -6, 0, 2, -1, -2 ], [ 4, -5, -1, 2, -1, -3 ], [ 5, -6, -1, 2, -1, -2 ] ], 1.5 ], - [ [ [ 3, -5, -1, 2, -1, -2 ], [ 5, -7, -1, 2, -1, -2 ], [ 4, -5, -1, 2, -1, -3 ], [ 5, -6, -1, 2, -1, -2 ] ], 1.125 ] - ], - [ - [ [ [ 3, -5, -1, 2, -1, -2 ], [ 5, -7, -1, 2, -1, -2 ], [ 4, -5, -1, 2, -1, -3 ], [ 5, -7, 0, 2, -1, -2 ] ], 0.75 ], - [ [ [ 3, -5, -1, 2, -1, -2 ], [ 5, -7, -1, 2, -1, -2 ], [ 4, -6, -1, 2, -1, -2 ], [ 5, -7, 0, 2, -1, -2 ] ], 1.5 ], - [ [ [ 5, -7, -1, 2, -1, -3 ], [ 5, -7, -1, 2, -1, -2 ], [ 4, -6, -1, 2, -1, -2 ], [ 5, -7, 0, 2, -1, -2 ] ], 1.625 ] - ], - [ - [ [ [ 5, -7, -1, 2, -1, -3 ], [ 4, -7, 0, 3, -1, -2 ], [ 4, -6, -1, 2, -1, -2 ], [ 5, -7, 0, 2, -1, -2 ] ], 1.375 ], - [ [ [ 5, -7, -1, 2, -1, -3 ], [ 4, -7, 0, 3, -1, -2 ], [ 6, -8, -1, 2, -1, -3 ], [ 5, -7, 0, 2, -1, -2 ] ], 0.375 ] - ], - [ - [ [ [ 5, -7, -1, 2, -1, -3 ], [ 4, -7, 0, 3, -1, -2 ], [ 3, -7, 0, 3, -1, -1 ], [ 5, -7, 0, 2, -1, -2 ] ], 1.125 ], - [ [ [ 4, -7, 0, 2, -1, -2 ], [ 4, -7, 0, 3, -1, -2 ], [ 3, -7, 0, 3, -1, -1 ], [ 5, -7, 0, 2, -1, -2 ] ], 0.875 ], - [ [ [ 4, -7, 0, 2, -1, -2 ], [ 4, -7, 0, 3, -1, -2 ], [ 3, -7, 0, 3, -1, -1 ], [ 5, -7, 0, 3, -1, -3 ] ], 1.125 ] - ], - [ - [ [ [ 3, -7, 0, 3, -1, -2 ], [ 4, -7, 0, 3, -1, -2 ], [ 3, -7, 0, 3, -1, -1 ], [ 5, -7, 0, 3, -1, -3 ] ], 0.75 ], - [ [ [ 3, -7, 0, 3, -1, -2 ], [ 4, -7, 0, 3, -1, -2 ], [ 3, -7, 0, 3, -1, -1 ], [ 5, -8, 0, 3, -1, -2 ] ], 0.625 ], - [ [ [ 3, -7, 0, 3, -1, -2 ], [ 4, -7, 0, 3, -1, -2 ], [ 3, -7, 0, 4, -1, -2 ], [ 5, -8, 0, 3, -1, -2 ] ], 1.125 ] - ], - [ - [ [ [ 3, -7, 0, 3, -1, -2 ], [ 4, -7, 0, 4, -1, -3 ], [ 3, -7, 0, 4, -1, -2 ], [ 5, -8, 0, 3, -1, -2 ] ], 0.5 ] - ], - [ - [ [ [ 3, -7, 0, 3, -1, -2 ], [ 4, -7, -1, 3, -1, -2 ], [ 3, -7, 0, 4, -1, -2 ], [ 5, -8, 0, 3, -1, -2 ] ], 0.625 ], - [ [ [ 3, -7, 0, 3, -1, -2 ], [ 4, -7, -1, 3, -1, -2 ], [ 4, -8, 0, 3, 0, -2 ], [ 5, -8, 0, 3, -1, -2 ] ], 1.625 ] - ], - [ - [ [ [ 3, -7, 0, 3, -1, -2 ], [ 4, -7, -1, 3, -1, -2 ], [ 4, -8, 0, 3, 0, -2 ], [ 5, -7, 0, 3, -2, -2 ] ], 1.125 ], - [ [ [ 3, -7, 0, 3, -1, -2 ], [ 4, -7, -1, 3, -1, -2 ], [ 4, -7, 0, 3, -1, -2 ], [ 5, -7, 0, 3, -2, -2 ] ], 1.625 ], - [ [ [ 3, -7, 0, 3, -1, -2 ], [ 3, -7, 0, 4, -1, -2 ], [ 4, -7, 0, 3, -1, -2 ], [ 5, -7, 0, 3, -2, -2 ] ], 1 ] - ], - [ - [ [ [ 3, -7, 0, 3, -1, -2 ], [ 3, -7, 0, 4, -1, -2 ], [ 4, -7, 0, 4, -1, -3 ], [ 5, -7, 0, 3, -2, -2 ] ], 0.875 ] - ], - [ - [ [ [ 4, -7, 0, 3, -3, -2 ], [ 3, -7, 0, 4, -1, -2 ], [ 4, -7, 0, 4, -1, -3 ], [ 5, -7, 0, 3, -2, -2 ] ], 1.625 ], - [ [ [ 4, -7, 0, 3, -3, -2 ], [ 3, -7, 0, 3, -1, -2 ], [ 4, -7, 0, 4, -1, -3 ], [ 5, -7, 0, 3, -2, -2 ] ], 1 ] - ], - [ - [ [ [ 4, -7, 0, 3, -3, -2 ], [ 3, -7, 0, 4, -1, -3 ], [ 4, -7, 0, 4, -1, -3 ], [ 5, -7, 0, 3, -2, -2 ] ], 0.75 ], - [ [ [ 4, -7, 0, 3, -3, -2 ], [ 3, -7, 0, 4, -1, -3 ], [ 4, -7, 0, 4, -1, -3 ], [ 5, -7, 0, 4, -1, -4 ] ], 1.5 ] - ], - [ - [ [ [ 4, -7, 0, 3, -3, -2 ], [ 3, -7, 0, 4, -1, -3 ], [ 3, -6, 0, 4, -1, -3 ], [ 5, -7, 0, 4, -1, -4 ] ], 1 ], - [ [ [ 3, -7, 0, 5, -1, -4 ], [ 3, -7, 0, 4, -1, -3 ], [ 3, -6, 0, 4, -1, -3 ], [ 5, -7, 0, 4, -1, -4 ] ], 0.625 ] - ], - [ - [ [ [ 3, -7, 0, 5, -1, -4 ], [ 3, -7, 0, 4, -1, -3 ], [ 5, -8, 0, 4, -1, -4 ], [ 5, -7, 0, 4, -1, -4 ] ], 1 ], - [ [ [ 3, -7, 0, 5, -1, -4 ], [ 3, -7, 0, 4, 0, -4 ], [ 5, -8, 0, 4, -1, -4 ], [ 5, -7, 0, 4, -1, -4 ] ], 0.5 ] - ], - [ - [ [ [ 3, -7, 0, 5, -1, -4 ], [ 3, -7, 0, 4, 0, -4 ], [ 5, -8, 0, 4, -1, -4 ], [ 4, -7, 1, 5, -1, -4 ] ], 1.25 ] - ], - [ - [ [ [ 4, -8, 0, 4, 0, -4 ], [ 3, -7, 0, 4, 0, -4 ], [ 5, -8, 0, 4, -1, -4 ], [ 4, -7, 1, 5, -1, -4 ] ], 1.75 ], - [ [ [ 4, -8, 0, 4, 0, -4 ], [ 3, -7, 0, 4, 0, -4 ], [ 3, -7, 0, 4, 0, -3 ], [ 4, -7, 1, 5, -1, -4 ] ], 1.75 ], - [ [ [ 4, -8, 0, 4, 0, -4 ], [ 3, -7, 0, 4, 0, -4 ], [ 3, -7, 0, 4, 0, -3 ], [ 4, -7, 0, 4, 1, -4 ] ], 1 ] - ], - [ - [ [ [ 4, -8, 0, 4, 0, -4 ], [ 3, -7, 0, 4, 0, -4 ], [ 3, -7, 0, 4, 2, -4 ], [ 4, -7, 0, 4, 1, -4 ] ], 1.25 ], - [ [ [ 4, -8, 0, 4, 0, -4 ], [ 3, -7, -1, 4, 1, -4 ], [ 3, -7, 0, 4, 2, -4 ], [ 4, -7, 0, 4, 1, -4 ] ], 0.625 ], - [ [ [ 2, -7, 0, 5, 1, -4 ], [ 3, -7, -1, 4, 1, -4 ], [ 3, -7, 0, 4, 2, -4 ], [ 4, -7, 0, 4, 1, -4 ] ], 0.875 ] - ], - [ - [ [ [ 2, -7, 0, 5, 1, -4 ], [ 3, -7, -1, 4, 1, -4 ], [ 3, -7, 0, 4, 2, -4 ], [ 3, -7, 0, 4, 2, -3 ] ], 0.875 ] - ], - [ - [ [ [ 2, -7, 0, 5, 1, -4 ], [ 3, -7, -1, 4, 1, -4 ], [ 3, -7, 0, 4, 2, -4 ], [ 4, -8, 0, 4, 2, -4 ] ], 0.5 ], - [ [ [ 2, -7, 0, 5, 1, -4 ], [ 3, -7, 0, 4, 2, -5 ], [ 3, -7, 0, 4, 2, -4 ], [ 4, -8, 0, 4, 2, -4 ] ], 1.375 ], - [ [ [ 2, -7, 0, 4, 3, -4 ], [ 3, -7, 0, 4, 2, -5 ], [ 3, -7, 0, 4, 2, -4 ], [ 4, -8, 0, 4, 2, -4 ] ], 0.5 ] - ], - [ - [ [ [ 2, -7, 0, 4, 3, -4 ], [ 3, -7, 0, 4, 2, -5 ], [ 3, -7, 0, 4, 2, -4 ], [ 3, -6, 0, 4, 2, -4 ] ], 1.375 ], - [ [ [ 2, -7, 0, 4, 3, -4 ], [ 3, -8, 0, 4, 2, -4 ], [ 3, -7, 0, 4, 2, -4 ], [ 3, -6, 0, 4, 2, -4 ] ], 0.375 ] - ], - [ - [ [ [ 1, -5, 0, 4, 2, -4 ], [ 3, -8, 0, 4, 2, -4 ], [ 3, -7, 0, 4, 2, -4 ], [ 3, -6, 0, 4, 2, -4 ] ], 1.375 ], - [ [ [ 1, -5, 0, 4, 2, -4 ], [ 2, -6, 0, 4, 2, -4 ], [ 3, -7, 0, 4, 2, -4 ], [ 3, -6, 0, 4, 2, -4 ] ], 1.125 ], - [ [ [ 1, -5, 0, 4, 2, -4 ], [ 2, -6, 0, 4, 2, -4 ], [ 2, -5, 0, 4, 2, -4 ], [ 3, -6, 0, 4, 2, -4 ] ], 1.5 ] - ], - [ - [ [ [ 2, -5, 0, 3, 2, -4 ], [ 2, -6, 0, 4, 2, -4 ], [ 2, -5, 0, 4, 2, -4 ], [ 3, -6, 0, 4, 2, -4 ] ], 1.5 ], - [ [ [ 2, -5, 0, 3, 2, -4 ], [ 1, -4, 0, 4, 2, -4 ], [ 2, -5, 0, 4, 2, -4 ], [ 3, -6, 0, 4, 2, -4 ] ], 1.125 ], - [ [ [ 2, -5, 0, 3, 2, -4 ], [ 1, -4, 0, 4, 2, -4 ], [ 2, -5, 0, 4, 2, -4 ], [ 3, -5, 0, 4, 1, -4 ] ], 0.625 ] - ], - [ - [ [ [ 2, -5, 0, 3, 2, -4 ], [ 1, -4, 0, 4, 2, -4 ], [ 2, -4, 0, 4, 1, -4 ], [ 3, -5, 0, 4, 1, -4 ] ], 1.25 ] - ], - [ - [ [ [ 2, -5, 0, 3, 2, -4 ], [ 3, -5, 0, 3, 1, -4 ], [ 2, -4, 0, 4, 1, -4 ], [ 3, -5, 0, 4, 1, -4 ] ], 1.75 ], - [ [ [ 2, -5, 0, 3, 2, -4 ], [ 3, -5, 0, 3, 1, -4 ], [ 3, -5, 0, 3, 2, -5 ], [ 3, -5, 0, 4, 1, -4 ] ], 1.625 ], - [ [ [ 2, -5, 0, 3, 2, -4 ], [ 3, -5, 0, 3, 1, -4 ], [ 3, -5, 0, 3, 2, -5 ], [ 3, -5, 0, 3, 2, -4 ] ], 0.625 ] - ], - [ - [ [ [ 3, -5, 0, 3, 0, -4 ], [ 3, -5, 0, 3, 1, -4 ], [ 3, -5, 0, 3, 2, -5 ], [ 3, -5, 0, 3, 2, -4 ] ], 1.625 ], - [ [ [ 3, -5, 0, 3, 0, -4 ], [ 3, -5, 0, 3, 1, -4 ], [ 3, -6, 0, 3, 2, -4 ], [ 3, -5, 0, 3, 2, -4 ] ], 1 ] - ], - [ - [ [ [ 3, -5, 0, 3, 0, -4 ], [ 3, -5, 0, 3, 1, -4 ], [ 3, -6, 0, 3, 2, -4 ], [ 3, -6, 0, 4, 2, -4 ] ], 1.375 ], - [ [ [ 2, -6, 1, 3, 2, -4 ], [ 3, -5, 0, 3, 1, -4 ], [ 3, -6, 0, 3, 2, -4 ], [ 3, -6, 0, 4, 2, -4 ] ], 1 ], - [ [ [ 2, -6, 1, 3, 2, -4 ], [ 3, -6, 1, 3, 2, -4 ], [ 3, -6, 0, 3, 2, -4 ], [ 3, -6, 0, 4, 2, -4 ] ], 0.75 ] - ], - [ - [ [ [ 2, -6, 1, 3, 2, -4 ], [ 3, -6, 0, 3, 3, -4 ], [ 3, -6, 0, 3, 2, -4 ], [ 3, -6, 0, 4, 2, -4 ] ], 0.875 ] - ], - [ - [ [ [ 2, -6, 0, 3, 3, -4 ], [ 3, -6, 0, 3, 3, -4 ], [ 3, -6, 0, 3, 2, -4 ], [ 3, -6, 0, 4, 2, -4 ] ], 1.5 ], - [ [ [ 2, -6, 0, 3, 3, -4 ], [ 3, -6, 0, 3, 3, -4 ], [ 3, -6, -1, 3, 3, -4 ], [ 3, -6, 0, 4, 2, -4 ] ], 0.5 ], - [ [ [ 2, -6, 0, 3, 3, -4 ], [ 3, -6, 0, 3, 3, -4 ], [ 3, -6, -1, 3, 3, -4 ], [ 3, -6, 0, 3, 4, -4 ] ], 1.5 ] - ], - [ - [ [ [ 2, -6, 0, 3, 3, -4 ], [ 3, -6, -1, 3, 4, -4 ], [ 3, -6, -1, 3, 3, -4 ], [ 3, -6, 0, 3, 4, -4 ] ], 1.125 ] - ], - [ - [ [ [ 2, -6, 0, 3, 3, -4 ], [ 4, -6, -2, 3, 3, -4 ], [ 3, -6, -1, 3, 3, -4 ], [ 3, -6, 0, 3, 4, -4 ] ], 1 ] - ], - [ - [ [ [ 2, -6, 0, 3, 3, -4 ], [ 4, -6, -2, 3, 3, -4 ], [ 3, -6, -1, 3, 3, -4 ], [ 3, -6, -2, 4, 3, -4 ] ], 1.625 ], - [ [ [ 2, -6, 0, 3, 3, -4 ], [ 4, -6, -2, 3, 3, -4 ], [ 3, -6, -2, 3, 4, -4 ], [ 3, -6, -2, 4, 3, -4 ] ], 0.625 ], - [ [ [ 2, -6, -2, 4, 3, -4 ], [ 4, -6, -2, 3, 3, -4 ], [ 3, -6, -2, 3, 4, -4 ], [ 3, -6, -2, 4, 3, -4 ] ], 1.625 ] - ], - [ - [ [ [ 2, -6, -2, 4, 3, -4 ], [ 3, -6, -1, 4, 3, -4 ], [ 3, -6, -2, 3, 4, -4 ], [ 3, -6, -2, 4, 3, -4 ] ], 1.375 ], - [ [ [ 2, -6, -2, 4, 3, -4 ], [ 3, -6, -1, 4, 3, -4 ], [ 2, -6, -2, 5, 3, -4 ], [ 3, -6, -2, 4, 3, -4 ] ], 0.5 ], - [ [ [ 1, -6, -2, 4, 3, -3 ], [ 3, -6, -1, 4, 3, -4 ], [ 2, -6, -2, 5, 3, -4 ], [ 3, -6, -2, 4, 3, -4 ] ], 1.625 ] - ], - [ - [ [ [ 1, -6, -2, 4, 3, -3 ], [ 2, -6, -2, 4, 3, -4 ], [ 2, -6, -2, 5, 3, -4 ], [ 3, -6, -2, 4, 3, -4 ] ], 1.125 ], - [ [ [ 1, -6, -2, 4, 3, -3 ], [ 2, -6, -2, 4, 3, -4 ], [ 3, -6, -2, 4, 3, -5 ], [ 3, -6, -2, 4, 3, -4 ] ], 1.125 ] - ], - [ - [ [ [ 1, -6, -2, 4, 3, -3 ], [ 2, -6, -2, 4, 3, -4 ], [ 3, -6, -2, 4, 3, -5 ], [ 3, -7, -2, 4, 3, -3 ] ], 1 ], - [ [ [ 1, -6, -2, 4, 3, -3 ], [ 2, -6, -2, 4, 3, -4 ], [ 1, -6, -2, 4, 3, -2 ], [ 3, -7, -2, 4, 3, -3 ] ], 0.875 ], - [ [ [ 1, -6, -2, 4, 3, -3 ], [ 2, -7, -2, 4, 3, -3 ], [ 1, -6, -2, 4, 3, -2 ], [ 3, -7, -2, 4, 3, -3 ] ], 1.125 ] - ], - [ - [ [ [ 1, -6, -2, 4, 3, -3 ], [ 3, -7, -2, 3, 3, -3 ], [ 1, -6, -2, 4, 3, -2 ], [ 3, -7, -2, 4, 3, -3 ] ], 1.75 ], - [ [ [ 1, -7, -2, 5, 3, -3 ], [ 3, -7, -2, 3, 3, -3 ], [ 1, -6, -2, 4, 3, -2 ], [ 3, -7, -2, 4, 3, -3 ] ], 1.5 ], - [ [ [ 1, -7, -2, 5, 3, -3 ], [ 3, -7, -2, 3, 3, -3 ], [ 2, -7, -2, 4, 4, -3 ], [ 3, -7, -2, 4, 3, -3 ] ], 0.75 ] - ], - [ - [ [ [ 1, -7, -2, 5, 3, -3 ], [ 3, -7, -2, 3, 3, -3 ], [ 2, -6, -2, 4, 3, -3 ], [ 3, -7, -2, 4, 3, -3 ] ], 0.625 ] - ], - [ - [ [ [ 1, -6, -1, 4, 3, -3 ], [ 3, -7, -2, 3, 3, -3 ], [ 2, -6, -2, 4, 3, -3 ], [ 3, -7, -2, 4, 3, -3 ] ], 1.375 ], - [ [ [ 1, -6, -1, 4, 3, -3 ], [ 3, -7, -2, 4, 3, -4 ], [ 2, -6, -2, 4, 3, -3 ], [ 3, -7, -2, 4, 3, -3 ] ], 1.625 ] - ], - [ - [ [ [ 1, -6, -1, 4, 3, -3 ], [ 3, -7, -2, 4, 3, -4 ], [ 2, -6, -1, 4, 3, -4 ], [ 3, -7, -2, 4, 3, -3 ] ], 0.875 ], - [ [ [ 1, -6, -1, 4, 3, -3 ], [ 3, -7, -2, 4, 3, -4 ], [ 2, -6, -1, 4, 3, -4 ], [ 3, -6, -1, 3, 3, -3 ] ], 1.625 ], - [ [ [ 1, -6, -1, 4, 3, -3 ], [ 2, -6, -1, 4, 2, -3 ], [ 2, -6, -1, 4, 3, -4 ], [ 3, -6, -1, 3, 3, -3 ] ], 1.375 ] - ], - [ - [ [ [ 1, -6, -1, 4, 3, -3 ], [ 0, -6, -1, 4, 3, -2 ], [ 2, -6, -1, 4, 3, -4 ], [ 3, -6, -1, 3, 3, -3 ] ], 1.5 ] - ], - [ - [ [ [ 1, -5, -1, 3, 3, -3 ], [ 0, -6, -1, 4, 3, -2 ], [ 2, -6, -1, 4, 3, -4 ], [ 3, -6, -1, 3, 3, -3 ] ], 1.625 ], - [ [ [ 1, -5, -1, 3, 3, -3 ], [ 0, -6, -1, 4, 3, -2 ], [ 3, -6, -1, 3, 3, -4 ], [ 3, -6, -1, 3, 3, -3 ] ], 1.625 ] - ], - [ - [ [ [ 1, -5, -1, 3, 3, -3 ], [ 1, -6, -1, 3, 3, -2 ], [ 3, -6, -1, 3, 3, -4 ], [ 3, -6, -1, 3, 3, -3 ] ], 1.875 ], - [ [ [ 1, -5, -1, 3, 3, -3 ], [ 1, -6, -1, 3, 3, -2 ], [ 1, -6, -1, 4, 3, -3 ], [ 3, -6, -1, 3, 3, -3 ] ], 1.5 ], - [ [ [ 2, -6, -2, 3, 3, -3 ], [ 1, -6, -1, 3, 3, -2 ], [ 1, -6, -1, 4, 3, -3 ], [ 3, -6, -1, 3, 3, -3 ] ], 0.625 ] - ], - [ - [ [ [ 2, -6, -1, 3, 2, -3 ], [ 1, -6, -1, 3, 3, -2 ], [ 1, -6, -1, 4, 3, -3 ], [ 3, -6, -1, 3, 3, -3 ] ], 1 ] - ], - [ - [ [ [ 0, -6, -1, 5, 3, -3 ], [ 1, -6, -1, 3, 3, -2 ], [ 1, -6, -1, 4, 3, -3 ], [ 3, -6, -1, 3, 3, -3 ] ], 1.75 ] - ], - [ - [ [ [ 0, -6, -1, 5, 3, -3 ], [ 1, -6, -1, 3, 3, -2 ], [ 2, -6, -1, 2, 3, -2 ], [ 3, -6, -1, 3, 3, -3 ] ], 0.625 ], - [ [ [ 1, -6, -1, 4, 3, -3 ], [ 1, -6, -1, 3, 3, -2 ], [ 2, -6, -1, 2, 3, -2 ], [ 3, -6, -1, 3, 3, -3 ] ], 0.875 ] - ], - [ - [ [ [ 1, -5, -1, 2, 3, -2 ], [ 1, -6, -1, 3, 3, -2 ], [ 2, -6, -1, 2, 3, -2 ], [ 3, -6, -1, 3, 3, -3 ] ], 0.875 ], - [ [ [ 1, -5, -1, 2, 3, -2 ], [ 1, -6, -1, 3, 3, -2 ], [ 2, -6, -1, 2, 3, -2 ], [ 4, -6, -1, 1, 3, -2 ] ], 1 ] - ], - [ - [ [ [ 3, -6, -1, 1, 2, -2 ], [ 1, -6, -1, 3, 3, -2 ], [ 2, -6, -1, 2, 3, -2 ], [ 4, -6, -1, 1, 3, -2 ] ], 1.375 ], - [ [ [ 3, -6, -1, 1, 2, -2 ], [ 2, -6, -1, 1, 3, -1 ], [ 2, -6, -1, 2, 3, -2 ], [ 4, -6, -1, 1, 3, -2 ] ], 0.5 ], - [ [ [ 3, -6, -1, 1, 2, -2 ], [ 2, -6, -1, 1, 3, -1 ], [ 3, -6, -1, 1, 3, -2 ], [ 4, -6, -1, 1, 3, -2 ] ], 1.5 ] - ], - [ - [ [ [ 3, -6, -1, 1, 2, -2 ], [ 2, -6, -1, 1, 3, -1 ], [ 3, -6, -1, 1, 3, -2 ], [ 3, -6, -1, 2, 3, -2 ] ], 0.625 ], - [ [ [ 3, -6, -2, 1, 3, -2 ], [ 2, -6, -1, 1, 3, -1 ], [ 3, -6, -1, 1, 3, -2 ], [ 3, -6, -1, 2, 3, -2 ] ], 1.75 ] - ], - [ - [ [ [ 3, -6, -2, 1, 3, -2 ], [ 2, -6, -1, 1, 3, -1 ], [ 3, -6, -2, 1, 4, -2 ], [ 3, -6, -1, 2, 3, -2 ] ], 1.25 ], - [ [ [ 3, -6, -2, 1, 3, -2 ], [ 4, -6, -2, 0, 3, -2 ], [ 3, -6, -2, 1, 4, -2 ], [ 3, -6, -1, 2, 3, -2 ] ], 1.625 ], - [ [ [ 3, -6, -2, 1, 3, -2 ], [ 4, -6, -2, 0, 3, -2 ], [ 3, -6, -2, 1, 4, -2 ], [ 5, -6, -2, 1, 3, -3 ] ], 0.875 ] - ], - [ - [ [ [ 3, -6, -2, 1, 3, -2 ], [ 4, -6, -2, 0, 3, -2 ], [ 3, -6, -2, 1, 4, -2 ], [ 4, -6, -2, 1, 3, -2 ] ], 1.125 ], - [ [ [ 3, -7, -2, 0, 3, -2 ], [ 4, -6, -2, 0, 3, -2 ], [ 3, -6, -2, 1, 4, -2 ], [ 4, -6, -2, 1, 3, -2 ] ], 0.375 ] - ], - [ - [ [ [ 3, -7, -2, 0, 3, -2 ], [ 2, -6, -2, 2, 3, -2 ], [ 3, -6, -2, 1, 4, -2 ], [ 4, -6, -2, 1, 3, -2 ] ], 1 ] - ], - [ - [ [ [ 1, -6, -2, 2, 3, -2 ], [ 2, -6, -2, 2, 3, -2 ], [ 3, -6, -2, 1, 4, -2 ], [ 4, -6, -2, 1, 3, -2 ] ], 0.5 ] - ], - [ - [ [ [ 2, -6, -2, 1, 2, -2 ], [ 2, -6, -2, 2, 3, -2 ], [ 3, -6, -2, 1, 4, -2 ], [ 4, -6, -2, 1, 3, -2 ] ], 0.875 ] - ], - [ - [ [ [ 2, -6, -2, 1, 2, -2 ], [ 2, -6, -2, 2, 3, -2 ], [ 3, -6, -2, 1, 4, -2 ], [ 4, -6, -2, 2, 3, -3 ] ], 1.125 ], - [ [ [ 2, -6, -2, 1, 2, -2 ], [ 2, -6, -2, 2, 3, -2 ], [ 3, -6, -2, 1, 3, -2 ], [ 4, -6, -2, 2, 3, -3 ] ], 0.5 ] - ], - [ - [ [ [ 2, -6, -2, 1, 2, -2 ], [ 2, -6, -2, 2, 3, -2 ], [ 4, -6, -2, 1, 1, -2 ], [ 4, -6, -2, 2, 3, -3 ] ], 1 ], - [ [ [ 2, -6, -2, 1, 2, -2 ], [ 3, -6, -2, 1, 3, -2 ], [ 4, -6, -2, 1, 1, -2 ], [ 4, -6, -2, 2, 3, -3 ] ], 1.625 ] - ], - [ - [ [ [ 2, -6, -2, 1, 2, -2 ], [ 3, -6, -2, 1, 3, -2 ], [ 4, -6, -2, 1, 1, -2 ], [ 6, -6, -2, 0, 1, -2 ] ], 1.375 ], - [ [ [ 3, -6, -2, 1, 0, -2 ], [ 3, -6, -2, 1, 3, -2 ], [ 4, -6, -2, 1, 1, -2 ], [ 6, -6, -2, 0, 1, -2 ] ], 1.5 ], - [ [ [ 3, -6, -2, 1, 0, -2 ], [ 3, -5, -2, 1, 1, -2 ], [ 4, -6, -2, 1, 1, -2 ], [ 6, -6, -2, 0, 1, -2 ] ], 0.5 ] - ], - [ - [ [ [ 3, -6, -2, 1, 0, -2 ], [ 5, -6, -2, 0, 0, -2 ], [ 4, -6, -2, 1, 1, -2 ], [ 6, -6, -2, 0, 1, -2 ] ], 1.25 ], - [ [ [ 4, -6, -2, 0, 0, -2 ], [ 5, -6, -2, 0, 0, -2 ], [ 4, -6, -2, 1, 1, -2 ], [ 6, -6, -2, 0, 1, -2 ] ], 0.5 ], - [ [ [ 4, -6, -2, 0, 0, -2 ], [ 5, -6, -2, 0, 0, -2 ], [ 5, -6, -2, 0, 1, -2 ], [ 6, -6, -2, 0, 1, -2 ] ], 0.625 ] - ], - [ - [ [ [ 5, -6, -2, -1, 0, -2 ], [ 5, -6, -2, 0, 0, -2 ], [ 5, -6, -2, 0, 1, -2 ], [ 6, -6, -2, 0, 1, -2 ] ], 1.625 ], - [ [ [ 5, -6, -2, -1, 0, -2 ], [ 5, -6, -2, 0, 0, -2 ], [ 5, -5, -2, 0, 0, -2 ], [ 6, -6, -2, 0, 1, -2 ] ], 1.625 ], - [ [ [ 5, -6, -2, -1, 0, -2 ], [ 5, -6, -2, 0, 0, -2 ], [ 5, -5, -2, 0, 0, -2 ], [ 7, -6, -2, 0, -1, -2 ] ], 1 ] - ], - [ - [ [ [ 5, -6, -2, -1, 0, -2 ], [ 4, -4, -2, 0, 0, -2 ], [ 5, -5, -2, 0, 0, -2 ], [ 7, -6, -2, 0, -1, -2 ] ], 1.625 ] - ], - [ - [ [ [ 5, -6, -2, -1, 0, -2 ], [ 4, -4, -2, 0, 0, -2 ], [ 7, -6, -2, -1, -1, -2 ], [ 7, -6, -2, 0, -1, -2 ] ], 1 ] - ], - [ - [ [ [ 6, -6, -2, -1, -2, -2 ], [ 4, -4, -2, 0, 0, -2 ], [ 7, -6, -2, -1, -1, -2 ], [ 7, -6, -2, 0, -1, -2 ] ], 0.5 ], - [ [ [ 6, -6, -2, -1, -2, -2 ], [ 7, -6, -2, -1, -2, -2 ], [ 7, -6, -2, -1, -1, -2 ], [ 7, -6, -2, 0, -1, -2 ] ], 1.375 ], - [ [ [ 6, -6, -2, -1, -2, -2 ], [ 7, -6, -2, -1, -2, -2 ], [ 7, -6, -2, -1, -1, -2 ], [ 7, -5, -2, -1, -1, -2 ] ], 1.125 ] - ], - [ - [ [ [ 6, -6, -2, -1, -2, -2 ], [ 7, -6, -3, -1, -1, -2 ], [ 7, -6, -2, -1, -1, -2 ], [ 7, -5, -2, -1, -1, -2 ] ], 0.625 ], - [ [ [ 6, -6, -3, -1, -1, -2 ], [ 7, -6, -3, -1, -1, -2 ], [ 7, -6, -2, -1, -1, -2 ], [ 7, -5, -2, -1, -1, -2 ] ], 0.875 ] - ], - [ - [ [ [ 6, -6, -3, -1, -1, -2 ], [ 7, -6, -3, -1, -1, -2 ], [ 7, -6, -2, -1, -1, -2 ], [ 8, -6, -3, -1, -1, -2 ] ], 0.625 ], - [ [ [ 6, -6, -3, -1, -1, -2 ], [ 8, -6, -3, -2, -1, -2 ], [ 7, -6, -2, -1, -1, -2 ], [ 8, -6, -3, -1, -1, -2 ] ], 1.5 ] - ], - [ - [ [ [ 6, -6, -3, -1, -1, -2 ], [ 8, -6, -3, -2, -1, -2 ], [ 7, -6, -2, -1, -1, -2 ], [ 7, -6, -2, 0, -1, -2 ] ], 1.125 ] - ], - [ - [ [ [ 6, -6, -3, -1, -1, -2 ], [ 8, -6, -3, -2, -1, -2 ], [ 7, -6, -2, -1, -1, -2 ], [ 7, -5, -3, -2, -1, -2 ] ], 0.375 ] - ], - [ - [ [ [ 6, -6, -3, -1, -1, -2 ], [ 8, -6, -3, -2, -1, -2 ], [ 7, -6, -2, -1, -1, -2 ], [ 7, -6, -2, -1, -2, -2 ] ], 1.5 ] - ], - [ - [ [ [ 6, -6, -3, -1, -1, -2 ], [ 8, -6, -3, -2, -1, -2 ], [ 7, -6, -2, -1, -1, -2 ], [ 6, -6, -2, -1, -1, -1 ] ], 1.25 ] - ], - [ - [ [ [ 6, -6, -3, -1, -1, -2 ], [ 8, -6, -3, -2, -1, -2 ], [ 7, -6, -2, -1, -1, -2 ], [ 6, -6, -2, 0, -1, -2 ] ], 1.625 ], - [ [ [ 6, -6, -3, -1, -1, -2 ], [ 7, -6, -2, -1, -2, -2 ], [ 7, -6, -2, -1, -1, -2 ], [ 6, -6, -2, 0, -1, -2 ] ], 1.75 ], - [ [ [ 5, -6, -2, 0, -1, -2 ], [ 7, -6, -2, -1, -2, -2 ], [ 7, -6, -2, -1, -1, -2 ], [ 6, -6, -2, 0, -1, -2 ] ], 0.5 ] - ], - [ - [ [ [ 5, -6, -2, 0, -1, -2 ], [ 7, -6, -2, -1, -2, -2 ], [ 7, -5, -2, -1, -2, -2 ], [ 6, -6, -2, 0, -1, -2 ] ], 1.5 ] - ], - [ - [ [ [ 5, -6, -2, 0, -1, -2 ], [ 7, -5, -2, -1, -3, -2 ], [ 7, -5, -2, -1, -2, -2 ], [ 6, -6, -2, 0, -1, -2 ] ], 1.375 ], - [ [ [ 5, -5, -2, 0, -2, -2 ], [ 7, -5, -2, -1, -3, -2 ], [ 7, -5, -2, -1, -2, -2 ], [ 6, -6, -2, 0, -1, -2 ] ], 1.25 ] - ], - [ - [ [ [ 5, -5, -2, 0, -2, -2 ], [ 7, -5, -2, -1, -3, -2 ], [ 8, -5, -2, -1, -4, -2 ], [ 6, -6, -2, 0, -1, -2 ] ], 0.75 ], - [ [ [ 5, -5, -2, 0, -2, -2 ], [ 7, -5, -2, -1, -3, -2 ], [ "Rest" ], [ 6, -6, -2, 0, -1, -2 ] ], 1.25 ], - [ [ [ "Rest" ], [ 7, -5, -2, -1, -3, -2 ], [ "Rest" ], [ 6, -6, -2, 0, -1, -2 ] ], 0.5 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 6, -6, -2, 0, -1, -2 ] ], 1.25 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 6.625 ] - ] - ] -], -"last_changes": -[ - [ [ 5, -6, -2, 0, -1, -2 ], [ 7, -6, -2, -1, -2, -2 ], [ 7, -6, -2, -1, -1, -2 ], [ 6, -6, -2, 0, -1, -2 ] ], - [ [ 5, -6, -2, 0, -1, -2 ], [ 7, -6, -2, -1, -2, -2 ], [ 7, -5, -2, -1, -2, -2 ], [ 6, -6, -2, 0, -1, -2 ] ], - [ [ 5, -6, -2, 0, -1, -2 ], [ 7, -5, -2, -1, -3, -2 ], [ 7, -5, -2, -1, -2, -2 ], [ 6, -6, -2, 0, -1, -2 ] ], - [ [ 5, -5, -2, 0, -2, -2 ], [ 7, -5, -2, -1, -3, -2 ], [ 7, -5, -2, -1, -2, -2 ], [ 6, -6, -2, 0, -1, -2 ] ], - [ [ 5, -5, -2, 0, -2, -2 ], [ 7, -5, -2, -1, -3, -2 ], [ 8, -5, -2, -1, -4, -2 ], [ 6, -6, -2, 0, -1, -2 ] ] -], -"cur_uid": "6a9928d6", -"ref_uid": "55f9b81e", -"order_seed": 963124, -"dur_seed": 397683, -"motifs_seed": 845264, -"entrances_probs_vals": [ 0, 0, 0, 0.41, 1.8406593406593, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 0.41, 1.8406593406593, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 0.41, 1.8406593406593, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2430, -293.49845201238 ], [ -869, 1211.1455108359 ], [ -832.19814241486, 1285 ], [ -702, 1211.1455108359 ] ], -"step_probs_vals": [ -1200, 1200, 0.0020576131687243, 0.068181818181818, 0.074074074074074, 0.0625, 0.20576131687243, 0.0625, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61316872427983, 0, 0.98971193415638, 0 ], -"passages_weights": [ 0.48, 0.46, 0.48, 1, 1 ], -"hd_exp": 1.52, -"hd_invert": 0, -"order": -[ - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 3 ], [ 1, 2, 0 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 3, 1 ], [ 2, 0 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 2 ], [ 0, 1, 3 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 3 ], [ 0, 2, 1 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 0, 1 ], [ 3, 2 ], [ ] ], - [ [ 2 ], [ 3, 0, 1 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 1 ], [ 2, 3, 0 ], [ ] ], - [ [ 3, 0 ], [ 2, 1 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 1, 0 ], [ 3, 2 ], [ ] ], - [ [ 3 ], [ 0, 1, 2 ], [ ] ], - [ [ 3 ], [ 1, 0, 2 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 1, 3 ], [ 2, 0 ], [ ] ], - [ [ 3 ], [ 1, 2, 0 ], [ ] ], - [ [ 3, 0 ], [ 2, 1 ], [ ] ], - [ [ 1 ], [ 3, 2, 0 ], [ ] ], - [ [ 3, 0 ], [ 1, 2 ], [ ] ], - [ [ 1 ], [ 2, 0, 3 ], [ ] ], - [ [ 1 ], [ 0, 3, 2 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 0, 3 ], [ 1, 2 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 0, 2 ], [ 1, 3 ], [ ] ], - [ [ 3, 1 ], [ 2, 0 ], [ ] ], - [ [ 3, 0 ], [ 2, 1 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 1 ], [ 0, 2, 3 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 2 ], [ 3, 1, 0 ], [ ] ], - [ [ 0, 2 ], [ 3, 1 ], [ ] ], - [ [ 3 ], [ 0, 1, 2 ], [ ] ], - [ [ 2 ], [ 0, 1, 3 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 0 ], [ 1, 2, 3 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 2 ], [ 3, 0, 1 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 1 ], [ 0, 2, 3 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 1 ], [ 3, 2, 0 ], [ ] ], - [ [ 3 ], [ 1, 2, 0 ], [ ] ], - [ [ 3, 0 ], [ 1, 2 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 3 ], [ 1, 0, 2 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 3, 2 ], [ 0, 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 1, 3 ], [ 0, 2 ], [ ] ], - [ [ 3 ], [ 1, 2, 0 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 1, 3 ], [ 2, 0 ], [ ] ], - [ [ 2, 1 ], [ 0, 3 ], [ ] ], - [ [ 3 ], [ 0, 1, 2 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 1, 3, 2 ], [ 0 ], [ ] ], - [ [ 1, 3, 2 ], [ 0 ], [ ] ], - [ [ 1, 0 ], [ 3, 2 ], [ ] ], - [ [ 3, 0 ], [ 2, 1 ], [ ] ], - [ [ 2 ], [ 3, 0, 1 ], [ ] ], - [ [ 3 ], [ 1, 0, 2 ], [ ] ], - [ [ 1 ], [ 0, 2, 3 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 2 ], [ 0, 1, 3 ], [ ] ], - [ [ 3, 2 ], [ 1, 0 ], [ ] ], - [ [ 0, 2 ], [ 3, 1 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 2 ], [ 3, 1, 0 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 3, 2 ], [ 1, 0 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 100, 100 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/6f0f638f/6f0f638f_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3/6f0f638f/6f0f638f_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/6f0f638f/6f0f638f_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/6f0f638f/6f0f638f_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3/6f0f638f/6f0f638f_mus_model.json deleted file mode 100644 index e65877d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/6f0f638f/6f0f638f_mus_model.json +++ /dev/null @@ -1,105 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, -1, -1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ 0, 0, 0, -1, -1, 0 ], [ "Rest" ], [ 1, 0, 0, -1, -1, 1 ], [ "Rest" ] ], 0 ], - [ [ [ 0, 0, 0, -1, -1, 0 ], [ "Rest" ], [ 1, 0, 0, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 2 ] ], 1.25 ], - [ [ [ 0, 0, 0, -1, -1, 0 ], [ 0, 0, 0, -1, -2, 2 ], [ 1, 0, 0, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 2 ] ], 1.5 ], - [ [ [ 0, 0, 0, -1, -1, 0 ], [ 0, -1, 0, -1, -1, 2 ], [ 1, 0, 0, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 2 ] ], 2.625 ] - ], - [ - [ [ [ 0, 0, 0, -1, -1, 0 ], [ "Rest" ], [ 1, 0, 0, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 2 ] ], 0 ], - [ [ [ -1, 0, -1, -1, -1, 2 ], [ "Rest" ], [ 1, 0, 0, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 2 ] ], 0 ], - [ [ [ -1, 0, -1, -1, -1, 2 ], [ "Rest" ], [ 1, -1, 0, -1, -1, 2 ], [ 1, 0, 0, -1, -1, 2 ] ], 1.25 ], - [ [ [ -1, 0, -1, -1, -1, 2 ], [ "Rest" ], [ 1, 0, 0, -1, -2, 2 ], [ 1, 0, 0, -1, -1, 2 ] ], 0.75 ], - [ [ [ -1, 0, -1, -1, -1, 2 ], [ "Rest" ], [ 0, 0, 0, -1, 0, 2 ], [ 1, 0, 0, -1, -1, 2 ] ], 1.5 ] - ], - [ - [ [ [ -1, 0, -1, -1, -1, 2 ], [ "Rest" ], [ 0, 0, 0, -1, 0, 2 ], [ "Rest" ] ], 0 ], - [ [ [ -1, 0, 0, -1, 0, 1 ], [ "Rest" ], [ 0, 0, 0, -1, 0, 2 ], [ "Rest" ] ], 0 ], - [ [ [ -1, 0, 0, -1, 0, 1 ], [ -1, 0, 0, -1, 0, 2 ], [ 0, 0, 0, -1, 0, 2 ], [ "Rest" ] ], 1.125 ], - [ [ [ -2, 0, 1, -1, 0, 2 ], [ -1, 0, 0, -1, 0, 2 ], [ 0, 0, 0, -1, 0, 2 ], [ "Rest" ] ], 2 ], - [ [ [ -1, 0, 0, -2, 0, 2 ], [ -1, 0, 0, -1, 0, 2 ], [ 0, 0, 0, -1, 0, 2 ], [ "Rest" ] ], 0.875 ], - [ [ [ 0, 0, 0, -2, 0, 2 ], [ -1, 0, 0, -1, 0, 2 ], [ 0, 0, 0, -1, 0, 2 ], [ "Rest" ] ], 0 ], - [ [ [ 0, 0, 0, -2, 0, 2 ], [ -1, 0, 1, -1, 0, 2 ], [ 0, 0, 0, -1, 0, 2 ], [ "Rest" ] ], 1.75 ] - ], - [ - [ [ [ 0, 0, 0, -2, 0, 2 ], [ -1, 0, 1, -1, 0, 2 ], [ 0, 0, 0, -1, 0, 2 ], [ 1, 0, 0, -1, -1, 2 ] ], 3 ], - [ [ [ 0, 0, 0, -2, 0, 2 ], [ -1, 0, 1, -1, 0, 2 ], [ 0, 0, 1, -1, -1, 2 ], [ 1, 0, 0, -1, -1, 2 ] ], 0 ], - [ [ [ 0, 0, 0, -2, 0, 2 ], [ 0, 0, -1, -1, -1, 2 ], [ 0, 0, 1, -1, -1, 2 ], [ 1, 0, 0, -1, -1, 2 ] ], 0.875 ], - [ [ [ 0, 0, 0, -2, 0, 2 ], [ -1, 1, 0, -1, -1, 2 ], [ 0, 0, 1, -1, -1, 2 ], [ 1, 0, 0, -1, -1, 2 ] ], 0 ], - [ [ [ 0, 0, 0, -2, 0, 2 ], [ -1, 1, 0, -1, -1, 2 ], [ 1, 0, 0, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 2 ] ], 1.625 ], - [ [ [ 0, 0, 0, -2, 0, 2 ], [ -1, 0, 0, -1, 0, 2 ], [ 1, 0, 0, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 2 ] ], 0 ], - [ [ [ 0, 0, 0, -2, 0, 2 ], [ -1, 0, 0, -1, 0, 2 ], [ 1, 0, 0, -2, -1, 2 ], [ 1, 0, 0, -1, -1, 2 ] ], 1.125 ] - ], - [ - [ [ [ 0, 0, 0, -2, 0, 2 ], [ -1, 0, 0, -1, 0, 2 ], [ -1, 0, 0, -1, 0, 3 ], [ 1, 0, 0, -1, -1, 2 ] ], 0 ], - [ [ [ 0, 0, 0, -1, 0, 1 ], [ -1, 0, 0, -1, 0, 2 ], [ -1, 0, 0, -1, 0, 3 ], [ 1, 0, 0, -1, -1, 2 ] ], 1.125 ], - [ [ [ 0, -1, 0, -1, 0, 2 ], [ -1, 0, 0, -1, 0, 2 ], [ -1, 0, 0, -1, 0, 3 ], [ 1, 0, 0, -1, -1, 2 ] ], 2.5 ] - ], - [ - [ [ [ 0, -1, 0, -1, 0, 2 ], [ -1, 0, 0, -1, 0, 2 ], [ -1, 0, 0, -1, 0, 3 ], [ -1, 0, 1, -1, 0, 3 ] ], 1.125 ], - [ [ [ 0, -1, 0, -1, 0, 2 ], [ -1, 0, 0, -1, 0, 2 ], [ -1, 0, 0, -1, 0, 3 ], [ 1, 0, 0, -2, 0, 2 ] ], 3 ] - ], - [ - [ [ [ 0, -1, 0, -1, 0, 2 ], [ -1, 0, 0, -1, 0, 2 ], [ -1, 0, 0, -1, 0, 3 ], [ "Rest" ] ], 0 ], - [ [ [ 0, -1, 0, -1, 0, 2 ], [ 0, -1, 0, -1, -1, 2 ], [ -1, 0, 0, -1, 0, 3 ], [ "Rest" ] ], 1.375 ], - [ [ [ 0, -1, 0, -1, 0, 2 ], [ 0, -2, 0, -1, 0, 2 ], [ -1, 0, 0, -1, 0, 3 ], [ "Rest" ] ], 2.5 ], - [ [ [ 0, -1, 0, -1, 0, 2 ], [ -1, -1, 1, -1, 0, 2 ], [ -1, 0, 0, -1, 0, 3 ], [ "Rest" ] ], 1 ], - [ [ [ 0, -1, 0, -1, 0, 2 ], [ -2, 0, 0, -1, 0, 3 ], [ -1, 0, 0, -1, 0, 3 ], [ "Rest" ] ], 2.125 ], - [ [ [ 0, -1, 0, -1, 0, 2 ], [ 0, -1, 0, -2, 0, 2 ], [ -1, 0, 0, -1, 0, 3 ], [ "Rest" ] ], 1.375 ] - ], - [ - [ [ [ -2, 1, 0, -1, 0, 3 ], [ 0, -1, 0, -2, 0, 2 ], [ -1, 0, 0, -1, 0, 3 ], [ "Rest" ] ], 1.625 ], - [ [ [ -2, 1, 0, -1, 0, 3 ], [ 0, -1, 0, -2, 0, 2 ], [ -1, 0, 0, -1, 0, 3 ], [ 0, -1, 0, -1, 0, 3 ] ], 0.5 ], - [ [ [ -2, 1, 0, -1, 0, 3 ], [ -1, 0, 1, -1, 0, 3 ], [ -1, 0, 0, -1, 0, 3 ], [ 0, -1, 0, -1, 0, 3 ] ], 0 ], - [ [ [ -2, 1, 0, -1, 0, 3 ], [ -1, 0, 1, -1, 0, 3 ], [ -1, 0, 0, -1, 0, 3 ], [ 0, 0, 0, -1, -1, 3 ] ], 2.5 ], - [ [ [ -2, 1, 0, -1, 0, 3 ], [ 0, -1, 0, -1, 0, 3 ], [ -1, 0, 0, -1, 0, 3 ], [ 0, 0, 0, -1, -1, 3 ] ], 0 ], - [ [ [ -2, 0, 0, -1, 1, 3 ], [ 0, -1, 0, -1, 0, 3 ], [ -1, 0, 0, -1, 0, 3 ], [ 0, 0, 0, -1, -1, 3 ] ], 1.125 ], - [ [ [ -2, 0, 0, -1, 1, 3 ], [ 0, -1, 0, -1, 0, 3 ], [ -1, 0, 0, -1, 0, 3 ], [ "Rest" ] ], 0 ], - [ [ [ -2, 0, 0, -1, 1, 3 ], [ "Rest" ], [ -1, 0, 0, -1, 0, 3 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ -1, 0, 0, -1, 0, 3 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0.875 ] - ] - ] -], -"last_changes": -[ - [ [ -2, 1, 0, -1, 0, 3 ], [ 0, -1, 0, -2, 0, 2 ], [ -1, 0, 0, -1, 0, 3 ], [ 0, -1, 0, -1, 0, 3 ] ], - [ [ -2, 1, 0, -1, 0, 3 ], [ -1, 0, 1, -1, 0, 3 ], [ -1, 0, 0, -1, 0, 3 ], [ 0, -1, 0, -1, 0, 3 ] ], - [ [ -2, 1, 0, -1, 0, 3 ], [ -1, 0, 1, -1, 0, 3 ], [ -1, 0, 0, -1, 0, 3 ], [ 0, 0, 0, -1, -1, 3 ] ], - [ [ -2, 1, 0, -1, 0, 3 ], [ 0, -1, 0, -1, 0, 3 ], [ -1, 0, 0, -1, 0, 3 ], [ 0, 0, 0, -1, -1, 3 ] ], - [ [ -2, 0, 0, -1, 1, 3 ], [ 0, -1, 0, -1, 0, 3 ], [ -1, 0, 0, -1, 0, 3 ], [ 0, 0, 0, -1, -1, 3 ] ] -], -"cur_uid": "6f0f638f", -"ref_uid": "781442dc", -"order_seed": 778672, -"dur_seed": 554838, -"motifs_seed": 420644, -"entrances_probs_vals": [ 0.76, 0, 0, 0.38461538461538, 3.08, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0.76, 0, 0, 0.38461538461538, 3.08, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0.76, 0, 0, 0.38461538461538, 3.08, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1984, 932.50773993808 ], [ -999, 951.08359133127 ], [ -15, 1043.9628482972 ], [ 78, 1081.1145510836 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.076131687242798, 0.91477272727273, 0.17489711934156, 0, 0.57818930041152, 0, 1, 0 ], -"passages_weights": [ 1, 1, 1, 1, 1 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 0, 2, 3 ], [ 1, 1 ], [ ] ], - [ [ 3 ], [ 0, 2, 2, 2 ], [ 1 ] ], - [ [ 2 ], [ 0, 1, 0, 0, 0, 1 ], [ 3 ] ], - [ [ 0, 3 ], [ 2, 1, 1, 2, 1, 2 ], [ ] ], - [ [ 1, 3 ], [ 2, 0, 0 ], [ ] ], - [ [ 2, 1, 0 ], [ 3, 3 ], [ ] ], - [ [ 2, 0 ], [ 1, 1, 1, 1, 1 ], [ 3 ] ], - [ [ 2 ], [ 0, 3, 1, 3, 1, 0 ], [ ] ] -], -"sus_weights": [ 1, 1, 1 ], -"order_size": [ 5, 10 ], -"passages_size": [ 0, 5 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/726a40c7/726a40c7_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3/726a40c7/726a40c7_code.scd deleted file mode 100644 index f822edb..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/726a40c7/726a40c7_code.scd +++ /dev/null @@ -1,946 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - if(pDistance < 0, {stepFunc.value(abs(pDistance))}, {0.001}); - //stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/726a40c7/726a40c7_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3/726a40c7/726a40c7_mus_model.json deleted file mode 100644 index 06e11db..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/726a40c7/726a40c7_mus_model.json +++ /dev/null @@ -1,163 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ 0, -1, 0, 2, 1, -2 ], [ "Rest" ], [ "Rest" ] ], 0.5 ], - [ [ [ -1, 0, 1, 2, 0, -2 ], [ 0, -1, 0, 2, 1, -2 ], [ "Rest" ], [ "Rest" ] ], 0.625 ], - [ [ [ -1, 0, 1, 2, 0, -2 ], [ 0, -1, 0, 2, 1, -2 ], [ -1, -1, 0, 3, 1, -2 ], [ "Rest" ] ], 0.25 ], - [ [ [ -1, 0, 1, 2, 0, -2 ], [ 0, -1, 0, 2, 1, -2 ], [ -1, -1, 0, 3, 1, -2 ], [ -1, -1, 0, 3, 1, -1 ] ], 0.875 ] - ], - [ - [ [ [ 0, -1, 0, 2, 0, -2 ], [ 0, -1, 0, 2, 1, -2 ], [ -1, -1, 0, 3, 1, -2 ], [ -1, -1, 0, 3, 1, -1 ] ], 1 ] - ], - [ - [ [ [ 0, -1, 0, 2, 0, -2 ], [ 0, -1, 0, 2, 1, -2 ], [ -2, -1, 1, 3, 1, -1 ], [ -1, -1, 0, 3, 1, -1 ] ], 0.375 ] - ], - [ - [ [ [ 0, -1, 0, 2, 0, -2 ], [ 0, -1, 0, 2, 1, -2 ], [ -2, -1, 1, 3, 1, -1 ], [ -2, -1, 1, 3, 1, 0 ] ], 0.625 ] - ], - [ - [ [ [ 0, -1, 0, 2, 0, -2 ], [ 0, -1, 0, 2, 1, -2 ], [ -2, -1, 1, 3, 1, -1 ], [ 1, -1, 0, 2, 0, -2 ] ], 1.125 ] - ], - [ - [ [ [ 0, -1, 0, 2, 0, -2 ], [ 0, -1, 0, 2, 1, -2 ], [ -2, -1, 1, 3, 1, -1 ], [ 0, 0, 0, 2, 1, -2 ] ], 0.125 ] - ], - [ - [ [ [ 0, -1, 0, 2, 0, -2 ], [ 0, -1, 0, 2, 1, -2 ], [ -2, -1, 1, 3, 1, -1 ], [ 0, -1, 0, 2, 1, -1 ] ], 0.75 ] - ], - [ - [ [ [ -1, 0, 0, 2, 1, -2 ], [ 0, -1, 0, 2, 1, -2 ], [ -2, -1, 1, 3, 1, -1 ], [ 0, -1, 0, 2, 1, -1 ] ], 0.625 ] - ], - [ - [ [ [ -1, 0, 0, 2, 1, -2 ], [ 0, -2, 0, 2, 1, -1 ], [ -2, -1, 1, 3, 1, -1 ], [ 0, -1, 0, 2, 1, -1 ] ], 0.875 ] - ], - [ - [ [ [ -1, 0, 0, 2, 1, -2 ], [ 0, -2, 0, 2, 1, -1 ], [ -2, -1, 1, 3, 1, -1 ], [ 1, -2, -1, 2, 1, -1 ] ], 1.125 ] - ], - [ - [ [ [ -1, 0, 0, 2, 1, -2 ], [ 0, -2, 0, 2, 1, -1 ], [ -1, 0, 1, 2, 1, -2 ], [ 1, -2, -1, 2, 1, -1 ] ], 0.375 ] - ], - [ - [ [ [ -1, 0, 0, 2, 1, -2 ], [ 0, -2, 0, 2, 1, -1 ], [ -1, 0, 1, 2, 1, -2 ], [ 1, 0, 0, 2, 1, -3 ] ], 0.875 ] - ], - [ - [ [ [ -1, 0, 0, 2, 1, -2 ], [ 0, -2, 0, 2, 1, -1 ], [ -1, 0, 1, 2, 1, -2 ], [ 0, 0, 1, 2, 1, -2 ] ], 0.5 ] - ], - [ - [ [ [ 0, -2, 0, 2, 0, -1 ], [ 0, -2, 0, 2, 1, -1 ], [ -1, 0, 1, 2, 1, -2 ], [ 0, 0, 1, 2, 1, -2 ] ], 0.75 ] - ], - [ - [ [ [ 0, -2, 0, 2, 0, -1 ], [ 0, 0, 1, 2, 1, -3 ], [ -1, 0, 1, 2, 1, -2 ], [ 0, 0, 1, 2, 1, -2 ] ], 1.125 ] - ], - [ - [ [ [ -2, 0, 1, 3, 1, -2 ], [ 0, 0, 1, 2, 1, -3 ], [ -1, 0, 1, 2, 1, -2 ], [ 0, 0, 1, 2, 1, -2 ] ], 0.625 ] - ], - [ - [ [ [ -2, 0, 1, 3, 1, -2 ], [ -1, 0, 1, 3, 0, -2 ], [ -1, 0, 1, 2, 1, -2 ], [ 0, 0, 1, 2, 1, -2 ] ], 0.5 ] - ], - [ - [ [ [ -2, 0, 1, 3, 1, -2 ], [ -1, 0, 1, 3, 0, -2 ], [ -1, 0, 0, 3, 0, -2 ], [ 0, 0, 1, 2, 1, -2 ] ], 1.125 ] - ], - [ - [ [ [ -2, 0, 1, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -1, 0, 0, 3, 0, -2 ], [ 0, 0, 1, 2, 1, -2 ] ], 0.125 ] - ], - [ - [ [ [ -2, 0, 1, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -2, 1, 0, 3, 1, -2 ], [ 0, 0, 1, 2, 1, -2 ] ], 0.125 ] - ], - [ - [ [ [ -3, 1, 0, 4, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -2, 1, 0, 3, 1, -2 ], [ 0, 0, 1, 2, 1, -2 ] ], 0.25 ] - ], - [ - [ [ [ -3, 2, 1, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -2, 1, 0, 3, 1, -2 ], [ 0, 0, 1, 2, 1, -2 ] ], 0.5 ] - ], - [ - [ [ [ -2, 0, 2, 2, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -2, 1, 0, 3, 1, -2 ], [ 0, 0, 1, 2, 1, -2 ] ], 0.875 ] - ], - [ - [ [ [ -2, 0, 2, 2, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -2, 1, 0, 3, 1, -2 ], [ -1, 1, 0, 3, 1, -2 ] ], 0.75 ] - ], - [ - [ [ [ -2, 1, 0, 3, 1, -3 ], [ -2, 1, 1, 3, 1, -2 ], [ -2, 1, 0, 3, 1, -2 ], [ -1, 1, 0, 3, 1, -2 ] ], 0 ] - ], - [ - [ [ [ -3, 1, 1, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -2, 1, 0, 3, 1, -2 ], [ -1, 1, 0, 3, 1, -2 ] ], 0.5 ] - ], - [ - [ [ [ -2, 0, 0, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -2, 1, 0, 3, 1, -2 ], [ -1, 1, 0, 3, 1, -2 ] ], 0.75 ] - ], - [ - [ [ [ -2, 0, 0, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -1, 0, -1, 3, 1, -2 ], [ -1, 1, 0, 3, 1, -2 ] ], 0.875 ] - ], - [ - [ [ [ -2, 0, 0, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -1, 0, -1, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -1 ] ], 0.75 ] - ], - [ - [ [ [ -2, 0, 0, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -3, 1, 1, 4, 1, -2 ], [ -2, 1, 1, 3, 1, -1 ] ], 0.125 ], - [ [ [ -2, 0, 0, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -3, 1, 1, 4, 1, -2 ], [ "Rest" ] ], 1 ], - [ [ [ -2, 0, 0, 3, 1, -2 ], [ "Rest" ], [ -3, 1, 1, 4, 1, -2 ], [ "Rest" ] ], 0.875 ], - [ [ [ "Rest" ], [ "Rest" ], [ -3, 1, 1, 4, 1, -2 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.75 ] - ] - ] -], -"last_changes": -[ - [ [ -3, 1, 1, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -2, 1, 0, 3, 1, -2 ], [ -1, 1, 0, 3, 1, -2 ] ], - [ [ -2, 0, 0, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -2, 1, 0, 3, 1, -2 ], [ -1, 1, 0, 3, 1, -2 ] ], - [ [ -2, 0, 0, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -1, 0, -1, 3, 1, -2 ], [ -1, 1, 0, 3, 1, -2 ] ], - [ [ -2, 0, 0, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -1, 0, -1, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -1 ] ], - [ [ -2, 0, 0, 3, 1, -2 ], [ -2, 1, 1, 3, 1, -2 ], [ -3, 1, 1, 4, 1, -2 ], [ -2, 1, 1, 3, 1, -1 ] ] -], -"cur_uid": "726a40c7", -"ref_uid": "5ec14635", -"order_seed": 439818, -"dur_seed": 544932, -"motifs_seed": 109123, -"entrances_probs_vals": [ 0, 0, 0, 0, 1.2087912087912, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 0, 1.2087912087912, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 0, 1.2087912087912, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2170, 338 ], [ -2373.9938080495, 1453 ], [ -1650, 1676 ], [ -1370.8978328173, 1694 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 1, 0, 0.2, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 1, 3, 2 ], [ 0 ], [ ] ], - [ [ 2, 0, 3 ], [ 1 ], [ ] ], - [ [ 1, 3, 2 ], [ 0 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ] -], -"sus_weights": [ 0, 0, 0.61 ], -"order_size": [ 30, 30 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/75316bf0/75316bf0_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3/75316bf0/75316bf0_code.scd deleted file mode 100644 index 49436ca..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/75316bf0/75316bf0_code.scd +++ /dev/null @@ -1,973 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - - - //isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/75316bf0/75316bf0_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3/75316bf0/75316bf0_mus_model.json deleted file mode 100644 index e03d000..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/75316bf0/75316bf0_mus_model.json +++ /dev/null @@ -1,550 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ 2, -1, -2, 2, -3, 0 ], [ "Rest" ], [ "Rest" ] ], 0.625 ], - [ [ [ "Rest" ], [ 2, -1, -2, 2, -3, 0 ], [ 2, -1, -2, 1, -3, 0 ], [ "Rest" ] ], 1 ], - [ [ [ "Rest" ], [ 2, -1, -2, 2, -3, 0 ], [ 2, -1, -2, 1, -3, 0 ], [ 1, 0, -2, 2, -3, 0 ] ], 1.5 ], - [ [ [ 1, -2, -2, 2, -3, 0 ], [ 2, -1, -2, 2, -3, 0 ], [ 2, -1, -2, 1, -3, 0 ], [ 1, 0, -2, 2, -3, 0 ] ], 1.875 ] - ], - [ - [ [ [ 1, -2, -2, 2, -3, 0 ], [ 2, -1, -2, 2, -3, 0 ], [ 2, -1, -2, 1, -3, 0 ], [ 2, -2, -1, 2, -3, 0 ] ], 1.625 ], - [ [ [ 1, -2, -2, 2, -3, 0 ], [ 3, -2, -2, 1, -3, 0 ], [ 2, -1, -2, 1, -3, 0 ], [ 2, -2, -1, 2, -3, 0 ] ], 1.5 ] - ], - [ - [ [ [ 1, -2, -2, 2, -3, 0 ], [ 3, -2, -2, 1, -3, 0 ], [ 2, -3, -2, 2, -3, 0 ], [ 2, -2, -1, 2, -3, 0 ] ], 1.5 ], - [ [ [ 1, -2, -2, 2, -3, 0 ], [ 3, -2, -2, 1, -3, 0 ], [ 2, -3, -2, 2, -3, 0 ], [ 3, -3, -2, 2, -3, 0 ] ], 0.875 ] - ], - [ - [ [ [ 2, -3, -3, 2, -3, 0 ], [ 3, -2, -2, 1, -3, 0 ], [ 2, -3, -2, 2, -3, 0 ], [ 3, -3, -2, 2, -3, 0 ] ], 1.125 ], - [ [ [ 2, -3, -3, 2, -3, 0 ], [ 3, -2, -2, 1, -3, 0 ], [ 3, -3, -2, 1, -3, 0 ], [ 3, -3, -2, 2, -3, 0 ] ], 1.75 ] - ], - [ - [ [ [ 2, -3, -3, 2, -3, 0 ], [ 3, -2, -2, 1, -3, 0 ], [ 3, -3, -2, 1, -3, 0 ], [ 4, -4, -3, 2, -3, 0 ] ], 1.5 ], - [ [ [ 2, -3, -3, 2, -3, 0 ], [ 4, -3, -3, 1, -3, 0 ], [ 3, -3, -2, 1, -3, 0 ], [ 4, -4, -3, 2, -3, 0 ] ], 1.5 ] - ], - [ - [ [ [ 2, -3, -3, 2, -3, 0 ], [ 3, -3, -2, 2, -3, 0 ], [ 3, -3, -2, 1, -3, 0 ], [ 4, -4, -3, 2, -3, 0 ] ], 1.75 ], - [ [ [ 2, -3, -3, 2, -3, 0 ], [ 3, -3, -2, 2, -3, 0 ], [ 3, -4, -3, 2, -3, 0 ], [ 4, -4, -3, 2, -3, 0 ] ], 1.5 ] - ], - [ - [ [ [ 2, -3, -3, 2, -3, 0 ], [ 3, -3, -2, 2, -3, 0 ], [ 2, -2, -3, 2, -3, 0 ], [ 4, -4, -3, 2, -3, 0 ] ], 0.5 ] - ], - [ - [ [ [ 2, -3, -3, 2, -3, 0 ], [ 4, -4, -4, 2, -3, 0 ], [ 2, -2, -3, 2, -3, 0 ], [ 4, -4, -3, 2, -3, 0 ] ], 0.5 ], - [ [ [ 2, -3, -3, 2, -3, 0 ], [ 4, -4, -4, 2, -3, 0 ], [ 2, -4, -3, 3, -3, 0 ], [ 4, -4, -3, 2, -3, 0 ] ], 0.75 ], - [ [ [ 3, -4, -4, 2, -3, 0 ], [ 4, -4, -4, 2, -3, 0 ], [ 2, -4, -3, 3, -3, 0 ], [ 4, -4, -3, 2, -3, 0 ] ], 0.625 ] - ], - [ - [ [ [ 3, -4, -4, 2, -3, 0 ], [ 4, -4, -4, 2, -3, 0 ], [ 3, -5, -3, 2, -3, 0 ], [ 4, -4, -3, 2, -3, 0 ] ], 0.625 ] - ], - [ - [ [ [ 1, -3, -4, 2, -3, 0 ], [ 4, -4, -4, 2, -3, 0 ], [ 3, -5, -3, 2, -3, 0 ], [ 4, -4, -3, 2, -3, 0 ] ], 1.25 ], - [ [ [ 1, -3, -4, 2, -3, 0 ], [ 4, -4, -4, 2, -3, 0 ], [ 2, -4, -4, 3, -3, 0 ], [ 4, -4, -3, 2, -3, 0 ] ], 1.375 ], - [ [ [ 1, -3, -4, 2, -3, 0 ], [ 4, -4, -4, 2, -3, 0 ], [ 2, -4, -4, 3, -3, 0 ], [ 5, -4, -4, 1, -3, 0 ] ], 0.75 ] - ], - [ - [ [ [ 1, -3, -4, 2, -3, 0 ], [ 4, -4, -4, 2, -3, 0 ], [ 3, -4, -4, 2, -3, 0 ], [ 5, -4, -4, 1, -3, 0 ] ], 1.375 ] - ], - [ - [ [ [ 1, -3, -4, 2, -3, 0 ], [ 4, -4, -4, 2, -3, 0 ], [ 3, -4, -4, 2, -3, 0 ], [ 4, -3, -5, 2, -3, 0 ] ], 1.5 ], - [ [ [ 1, -3, -4, 2, -3, 0 ], [ 3, -2, -4, 2, -3, 0 ], [ 3, -4, -4, 2, -3, 0 ], [ 4, -3, -5, 2, -3, 0 ] ], 0.5 ] - ], - [ - [ [ [ 1, -3, -4, 2, -3, 0 ], [ 3, -2, -4, 2, -3, 0 ], [ 3, -4, -4, 2, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 1.75 ], - [ [ [ 1, -3, -4, 2, -3, 0 ], [ 3, -2, -4, 2, -3, 0 ], [ 2, -2, -4, 2, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 1.625 ] - ], - [ - [ [ [ 1, -2, -4, 2, -4, 0 ], [ 3, -2, -4, 2, -3, 0 ], [ 2, -2, -4, 2, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 0.625 ] - ], - [ - [ [ [ 1, -2, -4, 2, -4, 0 ], [ 1, -2, -4, 3, -3, 0 ], [ 2, -2, -4, 2, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 0.875 ], - [ [ [ 1, -4, -4, 3, -3, 0 ], [ 1, -2, -4, 3, -3, 0 ], [ 2, -2, -4, 2, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 1.625 ] - ], - [ - [ [ [ 1, -4, -4, 3, -3, 0 ], [ 2, -4, -3, 3, -3, 0 ], [ 2, -2, -4, 2, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 1.625 ] - ], - [ - [ [ [ 1, -4, -4, 3, -3, 0 ], [ 2, -4, -3, 3, -3, 0 ], [ 2, -3, -4, 3, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 0.5 ] - ], - [ - [ [ [ 1, -4, -4, 3, -3, 0 ], [ 2, -4, -3, 3, -3, 0 ], [ 2, -4, -4, 3, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 0.75 ] - ], - [ - [ [ [ 1, -4, -4, 3, -3, 0 ], [ 2, -4, -3, 3, -3, 0 ], [ 1, -4, -3, 4, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 0.75 ], - [ [ [ 0, -4, -3, 4, -3, 0 ], [ 2, -4, -3, 3, -3, 0 ], [ 1, -4, -3, 4, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 1.25 ], - [ [ [ 0, -4, -3, 4, -3, 0 ], [ 2, -4, -3, 3, -3, 0 ], [ 1, -4, -3, 4, -3, 0 ], [ 3, -4, -3, 3, -3, 0 ] ], 1.25 ] - ], - [ - [ [ [ 0, -4, -3, 4, -3, 0 ], [ 3, -4, -3, 2, -3, 0 ], [ 1, -4, -3, 4, -3, 0 ], [ 3, -4, -3, 3, -3, 0 ] ], 1 ], - [ [ [ 0, -4, -3, 4, -3, 0 ], [ 3, -4, -3, 2, -3, 0 ], [ 2, -4, -3, 3, -3, 0 ], [ 3, -4, -3, 3, -3, 0 ] ], 0.375 ], - [ [ [ 1, -4, -3, 3, -3, 0 ], [ 3, -4, -3, 2, -3, 0 ], [ 2, -4, -3, 3, -3, 0 ], [ 3, -4, -3, 3, -3, 0 ] ], 1.375 ] - ], - [ - [ [ [ 1, -4, -3, 3, -3, 0 ], [ 3, -4, -3, 2, -3, 0 ], [ 2, -4, -3, 3, -3, 0 ], [ 4, -4, -3, 2, -3, 0 ] ], 1.625 ], - [ [ [ 2, -4, -3, 2, -3, 0 ], [ 3, -4, -3, 2, -3, 0 ], [ 2, -4, -3, 3, -3, 0 ], [ 4, -4, -3, 2, -3, 0 ] ], 1.625 ] - ], - [ - [ [ [ 2, -4, -3, 2, -3, 0 ], [ 3, -4, -3, 2, -3, 0 ], [ 2, -4, -3, 3, -3, 0 ], [ 3, -4, -3, 2, -3, 1 ] ], 1.625 ], - [ [ [ 2, -4, -3, 2, -3, 0 ], [ 3, -4, -3, 2, -3, 0 ], [ 3, -5, -3, 2, -3, 0 ], [ 3, -4, -3, 2, -3, 1 ] ], 1.75 ] - ], - [ - [ [ [ 2, -4, -3, 2, -3, 0 ], [ 3, -4, -3, 2, -3, 0 ], [ 2, -3, -3, 2, -3, 0 ], [ 3, -4, -3, 2, -3, 1 ] ], 1.75 ], - [ [ [ 2, -4, -3, 2, -3, 0 ], [ 3, -4, -3, 2, -3, 0 ], [ 2, -3, -3, 2, -3, 0 ], [ 3, -4, -3, 3, -3, 0 ] ], 1.75 ] - ], - [ - [ [ [ 2, -4, -3, 2, -3, 0 ], [ 2, -2, -3, 2, -3, 0 ], [ 2, -3, -3, 2, -3, 0 ], [ 3, -4, -3, 3, -3, 0 ] ], 1 ] - ], - [ - [ [ [ 2, -5, -3, 3, -3, 0 ], [ 2, -2, -3, 2, -3, 0 ], [ 2, -3, -3, 2, -3, 0 ], [ 3, -4, -3, 3, -3, 0 ] ], 1.625 ], - [ [ [ 2, -5, -3, 3, -3, 0 ], [ 2, -2, -3, 2, -3, 0 ], [ 2, -4, -3, 3, -3, 0 ], [ 3, -4, -3, 3, -3, 0 ] ], 1.75 ], - [ [ [ 2, -5, -3, 3, -3, 0 ], [ 2, -3, -3, 3, -3, 0 ], [ 2, -4, -3, 3, -3, 0 ], [ 3, -4, -3, 3, -3, 0 ] ], 1.625 ] - ], - [ - [ [ [ 1, -3, -3, 3, -3, 0 ], [ 2, -3, -3, 3, -3, 0 ], [ 2, -4, -3, 3, -3, 0 ], [ 3, -4, -3, 3, -3, 0 ] ], 1 ], - [ [ [ 1, -3, -3, 3, -3, 0 ], [ 2, -3, -3, 3, -3, 0 ], [ 2, -4, -3, 3, -3, 0 ], [ 2, -2, -3, 3, -3, 0 ] ], 1 ], - [ [ [ 1, -3, -3, 3, -3, 0 ], [ 2, -3, -3, 3, -3, 0 ], [ 1, -2, -3, 3, -3, 0 ], [ 2, -2, -3, 3, -3, 0 ] ], 1.25 ] - ], - [ - [ [ [ 1, -3, -3, 3, -3, 0 ], [ 2, -3, -3, 3, -3, 0 ], [ 2, -3, -4, 3, -3, 0 ], [ 2, -2, -3, 3, -3, 0 ] ], 0.875 ], - [ [ [ 1, -3, -3, 3, -3, 0 ], [ 2, -3, -3, 3, -3, 0 ], [ 2, -3, -4, 3, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 1.625 ], - [ [ [ 1, -3, -4, 3, -3, 0 ], [ 2, -3, -3, 3, -3, 0 ], [ 2, -3, -4, 3, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 0.875 ] - ], - [ - [ [ [ 1, -3, -4, 3, -3, 0 ], [ 2, -3, -3, 3, -3, 0 ], [ 2, -4, -4, 3, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 0.75 ], - [ [ [ 1, -3, -4, 3, -3, 0 ], [ 3, -4, -4, 3, -3, 0 ], [ 2, -4, -4, 3, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 0.5 ], - [ [ [ 1, -3, -4, 3, -3, 0 ], [ 3, -4, -4, 3, -3, 0 ], [ 2, -4, -4, 3, -3, 0 ], [ 2, -3, -4, 4, -3, 0 ] ], 1.125 ] - ], - [ - [ [ [ 1, -3, -4, 3, -3, 0 ], [ 3, -4, -4, 3, -3, 0 ], [ 1, -2, -4, 3, -3, 0 ], [ 2, -3, -4, 4, -3, 0 ] ], 1.625 ] - ], - [ - [ [ [ 1, -3, -4, 3, -3, 0 ], [ 2, -2, -4, 3, -3, 0 ], [ 1, -2, -4, 3, -3, 0 ], [ 2, -3, -4, 4, -3, 0 ] ], 1.75 ] - ], - [ - [ [ [ 1, -3, -4, 3, -3, 0 ], [ 2, -2, -4, 3, -3, 0 ], [ 1, -2, -4, 3, -3, 0 ], [ 2, -2, -3, 3, -3, 0 ] ], 1.75 ], - [ [ [ 1, -3, -4, 3, -3, 0 ], [ 2, -2, -4, 3, -3, 0 ], [ 2, -3, -5, 3, -3, 0 ], [ 2, -2, -3, 3, -3, 0 ] ], 0.75 ] - ], - [ - [ [ [ 1, -3, -4, 3, -3, 0 ], [ 2, -2, -4, 3, -3, 0 ], [ 2, -3, -5, 3, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 0.375 ], - [ [ [ 1, -3, -4, 3, -3, 0 ], [ 2, -3, -4, 3, -3, 0 ], [ 2, -3, -5, 3, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 1.125 ] - ], - [ - [ [ [ 1, -3, -4, 3, -3, 0 ], [ 2, -3, -4, 3, -4, 0 ], [ 2, -3, -5, 3, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 0.5 ], - [ [ [ 1, -3, -4, 2, -3, 0 ], [ 2, -3, -4, 3, -4, 0 ], [ 2, -3, -5, 3, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 1.75 ], - [ [ [ 1, -3, -4, 2, -3, 0 ], [ 2, -3, -4, 3, -4, 0 ], [ 1, -3, -4, 4, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 1.25 ] - ], - [ - [ [ [ 1, -3, -4, 2, -3, 0 ], [ 0, -2, -4, 4, -3, 0 ], [ 1, -3, -4, 4, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 1 ], - [ [ [ -1, -2, -4, 4, -3, 0 ], [ 0, -2, -4, 4, -3, 0 ], [ 1, -3, -4, 4, -3, 0 ], [ 3, -3, -4, 3, -3, 0 ] ], 1.75 ], - [ [ [ -1, -2, -4, 4, -3, 0 ], [ 0, -2, -4, 4, -3, 0 ], [ 1, -3, -4, 4, -3, 0 ], [ 2, -3, -4, 4, -3, 0 ] ], 0.875 ] - ], - [ - [ [ [ -1, -2, -4, 4, -3, 0 ], [ 0, -2, -4, 4, -3, 0 ], [ 0, -1, -4, 4, -3, 0 ], [ 2, -3, -4, 4, -3, 0 ] ], 1.375 ], - [ [ [ -1, -2, -4, 4, -3, 0 ], [ 0, -2, -4, 4, -3, 0 ], [ 0, -1, -4, 4, -3, 0 ], [ 1, -1, -4, 4, -3, 0 ] ], 1.25 ] - ], - [ - [ [ [ -1, -2, -4, 4, -3, 0 ], [ 1, -2, -4, 3, -3, 0 ], [ 0, -1, -4, 4, -3, 0 ], [ 1, -1, -4, 4, -3, 0 ] ], 0.625 ], - [ [ [ -1, -2, -4, 4, -3, 0 ], [ 1, -2, -4, 3, -3, 0 ], [ 0, -1, -4, 4, -3, 0 ], [ 1, -2, -3, 4, -3, 0 ] ], 0.625 ], - [ [ [ -1, -2, -4, 4, -3, 0 ], [ 1, -2, -4, 3, -3, 0 ], [ 0, -2, -4, 4, -3, 0 ], [ 1, -2, -3, 4, -3, 0 ] ], 0.5 ] - ], - [ - [ [ [ -1, -2, -4, 4, -3, 0 ], [ 0, -2, -3, 4, -3, 0 ], [ 0, -2, -4, 4, -3, 0 ], [ 1, -2, -3, 4, -3, 0 ] ], 0.75 ], - [ [ [ -1, -2, -4, 4, -3, 0 ], [ 0, -2, -3, 4, -3, 0 ], [ -1, -2, -3, 5, -3, 0 ], [ 1, -2, -3, 4, -3, 0 ] ], 1.125 ] - ], - [ - [ [ [ -1, -2, -4, 4, -3, 0 ], [ 1, -3, -4, 4, -3, 0 ], [ -1, -2, -3, 5, -3, 0 ], [ 1, -2, -3, 4, -3, 0 ] ], 1.625 ], - [ [ [ -1, -2, -4, 4, -3, 0 ], [ 1, -3, -4, 4, -3, 0 ], [ -1, -2, -3, 5, -3, 0 ], [ 2, -3, -4, 4, -3, 0 ] ], 0.875 ], - [ [ [ -1, -2, -4, 4, -3, 0 ], [ 1, -3, -4, 4, -3, 0 ], [ 0, -2, -3, 4, -3, 0 ], [ 2, -3, -4, 4, -3, 0 ] ], 1.25 ] - ], - [ - [ [ [ -1, -2, -4, 4, -3, 0 ], [ 1, -3, -4, 4, -3, 0 ], [ 1, -3, -4, 4, -4, 0 ], [ 2, -3, -4, 4, -3, 0 ] ], 1 ] - ], - [ - [ [ [ -1, -2, -4, 4, -3, 0 ], [ 1, -3, -4, 4, -3, 0 ], [ 1, -3, -4, 4, -4, 0 ], [ 1, -1, -4, 4, -3, 0 ] ], 1.5 ] - ], - [ - [ [ [ -1, -2, -4, 4, -3, 0 ], [ 1, -2, -4, 4, -4, 0 ], [ 1, -3, -4, 4, -4, 0 ], [ 1, -1, -4, 4, -3, 0 ] ], 1 ], - [ [ [ 1, -3, -4, 3, -4, 0 ], [ 1, -2, -4, 4, -4, 0 ], [ 1, -3, -4, 4, -4, 0 ], [ 1, -1, -4, 4, -3, 0 ] ], 1.25 ], - [ [ [ 1, -3, -4, 3, -4, 0 ], [ 1, -2, -4, 4, -4, 0 ], [ 1, -3, -4, 4, -4, 0 ], [ 2, -2, -4, 4, -4, 0 ] ], 0.5 ] - ], - [ - [ [ [ 1, -3, -4, 3, -4, 0 ], [ 1, -2, -4, 4, -4, 0 ], [ 2, -3, -4, 3, -4, 0 ], [ 2, -2, -4, 4, -4, 0 ] ], 1 ] - ], - [ - [ [ [ 1, -3, -4, 3, -4, 0 ], [ 2, -2, -4, 3, -4, 0 ], [ 2, -3, -4, 3, -4, 0 ], [ 2, -2, -4, 4, -4, 0 ] ], 0.875 ], - [ [ [ 0, -2, -4, 3, -4, 0 ], [ 2, -2, -4, 3, -4, 0 ], [ 2, -3, -4, 3, -4, 0 ], [ 2, -2, -4, 4, -4, 0 ] ], 1.75 ] - ], - [ - [ [ [ 0, -2, -4, 3, -4, 0 ], [ 2, -2, -4, 3, -4, 0 ], [ 2, -3, -4, 3, -4, 0 ], [ 2, -1, -4, 3, -4, 0 ] ], 1.75 ], - [ [ [ 0, -2, -4, 3, -4, 0 ], [ 2, -2, -4, 3, -4, 0 ], [ 1, -1, -4, 3, -4, 0 ], [ 2, -1, -4, 3, -4, 0 ] ], 1.75 ], - [ [ [ 1, -2, -4, 3, -4, 0 ], [ 2, -2, -4, 3, -4, 0 ], [ 1, -1, -4, 3, -4, 0 ], [ 2, -1, -4, 3, -4, 0 ] ], 1.125 ] - ], - [ - [ [ [ 1, -2, -4, 3, -4, 0 ], [ 1, 0, -4, 3, -4, 0 ], [ 1, -1, -4, 3, -4, 0 ], [ 2, -1, -4, 3, -4, 0 ] ], 0.875 ] - ], - [ - [ [ [ 0, 0, -4, 3, -4, 0 ], [ 1, 0, -4, 3, -4, 0 ], [ 1, -1, -4, 3, -4, 0 ], [ 2, -1, -4, 3, -4, 0 ] ], 1.75 ], - [ [ [ 0, 0, -4, 3, -4, 0 ], [ 1, 0, -4, 3, -4, 0 ], [ 0, 1, -4, 3, -4, 0 ], [ 2, -1, -4, 3, -4, 0 ] ], 0.625 ] - ], - [ - [ [ [ -1, 1, -4, 3, -4, 0 ], [ 1, 0, -4, 3, -4, 0 ], [ 0, 1, -4, 3, -4, 0 ], [ 2, -1, -4, 3, -4, 0 ] ], 0.75 ], - [ [ [ -1, 1, -4, 3, -4, 0 ], [ 1, 0, -4, 3, -4, 0 ], [ 1, 0, -5, 3, -4, 0 ], [ 2, -1, -4, 3, -4, 0 ] ], 0.75 ] - ], - [ - [ [ [ -1, 1, -4, 3, -4, 0 ], [ 1, 0, -4, 3, -4, 0 ], [ 1, 0, -5, 3, -4, 0 ], [ 1, 1, -4, 3, -4, 0 ] ], 1.5 ], - [ [ [ -1, 1, -4, 3, -4, 0 ], [ 1, 0, -4, 3, -4, 0 ], [ 0, 0, -4, 4, -4, 0 ], [ 1, 1, -4, 3, -4, 0 ] ], 1.25 ], - [ [ [ -1, 0, -4, 3, -4, 0 ], [ 1, 0, -4, 3, -4, 0 ], [ 0, 0, -4, 4, -4, 0 ], [ 1, 1, -4, 3, -4, 0 ] ], 0.875 ] - ], - [ - [ [ [ -1, 0, -4, 4, -4, -1 ], [ 1, 0, -4, 3, -4, 0 ], [ 0, 0, -4, 4, -4, 0 ], [ 1, 1, -4, 3, -4, 0 ] ], 0.75 ], - [ [ [ -1, 0, -4, 4, -4, -1 ], [ 1, 0, -4, 3, -4, 0 ], [ 0, 0, -4, 4, -4, 0 ], [ 0, 1, -4, 4, -4, 0 ] ], 1 ], - [ [ [ -1, 0, -4, 4, -4, -1 ], [ 0, 0, -3, 4, -4, 0 ], [ 0, 0, -4, 4, -4, 0 ], [ 0, 1, -4, 4, -4, 0 ] ], 1.5 ] - ], - [ - [ [ [ -1, 0, -4, 4, -4, -1 ], [ 1, 0, -5, 4, -4, -1 ], [ 0, 0, -4, 4, -4, 0 ], [ 0, 1, -4, 4, -4, 0 ] ], 1.625 ], - [ [ [ -1, 0, -4, 4, -4, -1 ], [ 1, 0, -5, 4, -4, -1 ], [ 0, 0, -4, 4, -4, 0 ], [ 2, -1, -4, 4, -4, -1 ] ], 0.5 ], - [ [ [ -1, 0, -4, 4, -4, -1 ], [ 1, 0, -5, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 0.75 ] - ], - [ - [ [ [ -1, 0, -4, 4, -4, -1 ], [ 2, -2, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 0.5 ], - [ [ [ 0, -1, -5, 4, -4, -1 ], [ 2, -2, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 1.375 ], - [ [ [ 0, -1, -5, 4, -4, -1 ], [ 2, -2, -4, 4, -4, -1 ], [ 1, -1, -5, 4, -4, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 0.625 ] - ], - [ - [ [ [ 0, -1, -5, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 1, -1, -5, 4, -4, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 0.625 ], - [ [ [ 0, -1, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 1, -1, -5, 4, -4, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 1 ], - [ [ [ 0, -1, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 0, 0, -4, 4, -4, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 1 ] - ], - [ - [ [ [ 0, -1, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 0, -1, -4, 5, -4, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 1 ], - [ [ [ 0, -2, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 0, -1, -4, 5, -4, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 1.375 ] - ], - [ - [ [ [ 0, -2, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 2, -2, -4, 4, -4, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 1.25 ], - [ [ [ 0, -2, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 2, -2, -4, 4, -4, -1 ], [ 3, -3, -4, 4, -4, -1 ] ], 0.875 ] - ], - [ - [ [ [ 0, -3, -4, 4, -3, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 2, -2, -4, 4, -4, -1 ], [ 3, -3, -4, 4, -4, -1 ] ], 0.875 ] - ], - [ - [ [ [ 0, -2, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 2, -2, -4, 4, -4, -1 ], [ 3, -3, -4, 4, -4, -1 ] ], 0.875 ], - [ [ [ 0, -2, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 2, -2, -4, 4, -4, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 1.5 ], - [ [ [ 0, -2, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 1, 0, -4, 4, -4, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 0.875 ] - ], - [ - [ [ [ 0, -2, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 2, -3, -4, 4, -4, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 1.5 ], - [ [ [ 0, -2, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 2, -3, -4, 4, -4, -1 ], [ 2, -2, -4, 4, -4, 0 ] ], 0.375 ] - ], - [ - [ [ [ 0, -2, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 2, -3, -4, 4, -4, -1 ], [ 1, -1, -4, 5, -4, -1 ] ], 0.5 ], - [ [ [ 0, -2, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 0, 0, -4, 4, -4, -1 ], [ 1, -1, -4, 5, -4, -1 ] ], 0.75 ] - ], - [ - [ [ [ 0, -2, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 1, -1, -5, 4, -4, -1 ], [ 1, -1, -4, 5, -4, -1 ] ], 0.5 ] - ], - [ - [ [ [ 0, -2, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 1, -2, -4, 4, -3, -1 ], [ 1, -1, -4, 5, -4, -1 ] ], 0.5 ], - [ [ [ 0, -2, -4, 4, -4, -1 ], [ 2, -2, -5, 4, -4, -1 ], [ 1, -2, -4, 4, -3, -1 ], [ 1, -1, -4, 5, -4, -1 ] ], 1.125 ], - [ [ [ 0, -2, -4, 4, -4, -1 ], [ 2, -2, -5, 4, -4, -1 ], [ 1, -2, -4, 4, -3, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 1.625 ] - ], - [ - [ [ [ 0, -2, -4, 4, -4, -1 ], [ 2, -2, -5, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 0.875 ] - ], - [ - [ [ [ 0, -2, -4, 4, -4, -1 ], [ 0, 0, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 1.375 ], - [ [ [ -1, 0, -4, 4, -4, -1 ], [ 0, 0, -4, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 0.875 ] - ], - [ - [ [ [ -1, 0, -4, 4, -4, -1 ], [ 1, -1, -5, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 1.5 ], - [ [ [ -1, 0, -4, 4, -4, -1 ], [ 1, -1, -5, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 1, -1, -4, 5, -4, -1 ] ], 0.5 ], - [ [ [ 0, -1, -5, 4, -4, -1 ], [ 1, -1, -5, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 1, -1, -4, 5, -4, -1 ] ], 1.375 ] - ], - [ - [ [ [ 0, -1, -5, 4, -4, -1 ], [ 1, -1, -5, 4, -4, -1 ], [ 1, -1, -4, 4, -4, -1 ], [ 3, -1, -5, 4, -4, -2 ] ], 0.625 ], - [ [ [ 0, -1, -5, 4, -4, -1 ], [ 1, -1, -5, 4, -4, -1 ], [ 2, -2, -5, 4, -4, -1 ], [ 3, -1, -5, 4, -4, -2 ] ], 1.5 ] - ], - [ - [ [ [ 0, -1, -5, 4, -4, -1 ], [ 2, -3, -5, 4, -4, -1 ], [ 2, -2, -5, 4, -4, -1 ], [ 3, -1, -5, 4, -4, -2 ] ], 1.5 ], - [ [ [ 1, -2, -5, 4, -4, -2 ], [ 2, -3, -5, 4, -4, -1 ], [ 2, -2, -5, 4, -4, -1 ], [ 3, -1, -5, 4, -4, -2 ] ], 0.5 ], - [ [ [ 1, -2, -5, 4, -4, -2 ], [ 2, -3, -5, 4, -4, -1 ], [ 2, -2, -5, 4, -4, -1 ], [ 3, -2, -5, 4, -4, -1 ] ], 1.25 ] - ], - [ - [ [ [ 1, -2, -5, 4, -4, -2 ], [ 2, -2, -5, 4, -5, -1 ], [ 2, -2, -5, 4, -4, -1 ], [ 3, -2, -5, 4, -4, -1 ] ], 0.625 ], - [ [ [ 1, -3, -5, 4, -4, -1 ], [ 2, -2, -5, 4, -5, -1 ], [ 2, -2, -5, 4, -4, -1 ], [ 3, -2, -5, 4, -4, -1 ] ], 0.75 ], - [ [ [ 1, -3, -5, 4, -4, -1 ], [ 2, -2, -5, 4, -5, -1 ], [ 2, -3, -5, 4, -4, -1 ], [ 3, -2, -5, 4, -4, -1 ] ], 1.625 ] - ], - [ - [ [ [ 1, -2, -5, 4, -5, -1 ], [ 2, -2, -5, 4, -5, -1 ], [ 2, -3, -5, 4, -4, -1 ], [ 3, -2, -5, 4, -4, -1 ] ], 1.5 ], - [ [ [ 1, -2, -5, 4, -5, -1 ], [ 2, -2, -5, 4, -5, -1 ], [ 3, -2, -5, 4, -5, -1 ], [ 3, -2, -5, 4, -4, -1 ] ], 0.5 ], - [ [ [ 1, -2, -5, 4, -5, -1 ], [ 2, -2, -5, 4, -5, -1 ], [ 3, -2, -5, 4, -5, -1 ], [ 3, -2, -4, 4, -5, -1 ] ], 1.5 ] - ], - [ - [ [ [ 1, -2, -5, 4, -5, -1 ], [ 2, -2, -5, 4, -5, -1 ], [ 2, -2, -4, 4, -5, -1 ], [ 3, -2, -4, 4, -5, -1 ] ], 1.375 ], - [ [ [ 1, -2, -5, 4, -5, -1 ], [ 1, -2, -4, 5, -5, -1 ], [ 2, -2, -4, 4, -5, -1 ], [ 3, -2, -4, 4, -5, -1 ] ], 0.625 ], - [ [ [ 0, -2, -4, 5, -5, -1 ], [ 1, -2, -4, 5, -5, -1 ], [ 2, -2, -4, 4, -5, -1 ], [ 3, -2, -4, 4, -5, -1 ] ], 0.75 ] - ], - [ - [ [ [ 0, -2, -4, 5, -5, -1 ], [ 1, -1, -4, 4, -5, -1 ], [ 2, -2, -4, 4, -5, -1 ], [ 3, -2, -4, 4, -5, -1 ] ], 0.875 ], - [ [ [ 0, -2, -4, 5, -5, -1 ], [ 1, -1, -4, 4, -5, -1 ], [ 2, -2, -4, 4, -5, -1 ], [ 4, -2, -4, 3, -5, -1 ] ], 1 ] - ], - [ - [ [ [ 1, -2, -4, 4, -5, -1 ], [ 1, -1, -4, 4, -5, -1 ], [ 2, -2, -4, 4, -5, -1 ], [ 4, -2, -4, 3, -5, -1 ] ], 0.75 ] - ], - [ - [ [ [ 1, -2, -4, 4, -5, -1 ], [ 1, -1, -4, 4, -5, -1 ], [ 2, -2, -4, 4, -5, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 0.75 ] - ], - [ - [ [ [ 1, -2, -4, 4, -5, -1 ], [ 2, -1, -4, 4, -5, -1 ], [ 2, -2, -4, 4, -5, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 0.875 ], - [ [ [ 1, -2, -4, 4, -5, -1 ], [ 2, -1, -4, 4, -5, -1 ], [ 1, -1, -4, 4, -5, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 1.25 ], - [ [ [ 0, -1, -4, 4, -5, -1 ], [ 2, -1, -4, 4, -5, -1 ], [ 1, -1, -4, 4, -5, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 1.125 ] - ], - [ - [ [ [ 1, -1, -4, 3, -5, -1 ], [ 2, -1, -4, 4, -5, -1 ], [ 1, -1, -4, 4, -5, -1 ], [ 2, -1, -4, 4, -4, -1 ] ], 1 ], - [ [ [ 1, -1, -4, 3, -5, -1 ], [ 2, -1, -4, 4, -5, -1 ], [ 1, -1, -4, 4, -5, -1 ], [ 2, 0, -4, 4, -5, -1 ] ], 1.375 ] - ], - [ - [ [ [ 0, -1, -3, 4, -5, -1 ], [ 2, -1, -4, 4, -5, -1 ], [ 1, -1, -4, 4, -5, -1 ], [ 2, 0, -4, 4, -5, -1 ] ], 0.75 ], - [ [ [ 0, -1, -3, 4, -5, -1 ], [ 2, -1, -4, 4, -5, -1 ], [ 2, -1, -4, 3, -5, -1 ], [ 2, 0, -4, 4, -5, -1 ] ], 1.5 ], - [ [ [ 0, -1, -3, 4, -5, -1 ], [ 2, -1, -4, 4, -5, -1 ], [ 2, -1, -4, 3, -5, -1 ], [ 3, -2, -4, 4, -5, -1 ] ], 0.5 ] - ], - [ - [ [ [ 1, -2, -4, 4, -5, -1 ], [ 2, -1, -4, 4, -5, -1 ], [ 2, -1, -4, 3, -5, -1 ], [ 3, -2, -4, 4, -5, -1 ] ], 1.375 ], - [ [ [ 1, -2, -4, 4, -5, -1 ], [ 2, -1, -4, 4, -5, -1 ], [ 2, -2, -4, 4, -5, -1 ], [ 3, -2, -4, 4, -5, -1 ] ], 0.875 ], - [ [ [ 1, -2, -4, 4, -5, -1 ], [ 3, -2, -5, 4, -5, -1 ], [ 2, -2, -4, 4, -5, -1 ], [ 3, -2, -4, 4, -5, -1 ] ], 0.5 ] - ], - [ - [ [ [ 1, -2, -4, 4, -5, -1 ], [ 3, -2, -5, 4, -5, -1 ], [ 2, -2, -4, 4, -5, -1 ], [ 4, -3, -5, 4, -5, -1 ] ], 0.875 ] - ], - [ - [ [ [ 1, -2, -4, 4, -5, -1 ], [ 2, -2, -4, 5, -5, -1 ], [ 2, -2, -4, 4, -5, -1 ], [ 4, -3, -5, 4, -5, -1 ] ], 1 ], - [ [ [ 2, -3, -5, 4, -5, -1 ], [ 2, -2, -4, 5, -5, -1 ], [ 2, -2, -4, 4, -5, -1 ], [ 4, -3, -5, 4, -5, -1 ] ], 1.5 ] - ], - [ - [ [ [ 2, -3, -5, 4, -5, -1 ], [ 2, -2, -4, 5, -5, -1 ], [ 2, -2, -4, 4, -5, -1 ], [ 3, -3, -4, 5, -5, -1 ] ], 1.375 ], - [ [ [ 1, -3, -4, 5, -5, -1 ], [ 2, -2, -4, 5, -5, -1 ], [ 2, -2, -4, 4, -5, -1 ], [ 3, -3, -4, 5, -5, -1 ] ], 1.25 ], - [ [ [ 1, -3, -4, 5, -5, -1 ], [ 2, -2, -4, 5, -5, -1 ], [ 2, -3, -4, 5, -5, -1 ], [ 3, -3, -4, 5, -5, -1 ] ], 0.5 ] - ], - [ - [ [ [ 1, -3, -4, 5, -5, -1 ], [ 2, -2, -4, 5, -5, -1 ], [ 1, -2, -4, 5, -5, -1 ], [ 3, -3, -4, 5, -5, -1 ] ], 0.75 ], - [ [ [ 1, -3, -4, 5, -5, -1 ], [ 2, -3, -4, 5, -5, -1 ], [ 1, -2, -4, 5, -5, -1 ], [ 3, -3, -4, 5, -5, -1 ] ], 1.5 ] - ], - [ - [ [ [ 1, -3, -4, 5, -5, -1 ], [ 2, -4, -4, 5, -5, -1 ], [ 1, -2, -4, 5, -5, -1 ], [ 3, -3, -4, 5, -5, -1 ] ], 1.75 ], - [ [ [ 1, -3, -4, 5, -5, -1 ], [ 2, -4, -4, 5, -5, -1 ], [ 2, -3, -5, 5, -5, -1 ], [ 3, -3, -4, 5, -5, -1 ] ], 1.125 ], - [ [ [ 1, -4, -4, 5, -5, -1 ], [ 2, -4, -4, 5, -5, -1 ], [ 2, -3, -5, 5, -5, -1 ], [ 3, -3, -4, 5, -5, -1 ] ], 1.75 ] - ], - [ - [ [ [ 2, -4, -4, 4, -5, -1 ], [ 2, -4, -4, 5, -5, -1 ], [ 2, -3, -5, 5, -5, -1 ], [ 3, -3, -4, 5, -5, -1 ] ], 1.25 ], - [ [ [ 2, -4, -4, 4, -5, -1 ], [ 2, -4, -4, 5, -5, -1 ], [ 2, -3, -5, 5, -5, -1 ], [ 3, -3, -5, 5, -5, -1 ] ], 1.5 ] - ], - [ - [ [ [ 1, -3, -5, 5, -5, -1 ], [ 2, -4, -4, 5, -5, -1 ], [ 2, -3, -5, 5, -5, -1 ], [ 3, -3, -5, 5, -5, -1 ] ], 1.375 ], - [ [ [ 1, -3, -5, 5, -5, -1 ], [ 3, -4, -5, 5, -5, -1 ], [ 2, -3, -5, 5, -5, -1 ], [ 3, -3, -5, 5, -5, -1 ] ], 1.625 ] - ], - [ - [ [ [ 1, -4, -5, 5, -5, -1 ], [ 3, -4, -5, 5, -5, -1 ], [ 2, -3, -5, 5, -5, -1 ], [ 3, -3, -5, 5, -5, -1 ] ], 1 ] - ], - [ - [ [ [ 1, -4, -5, 5, -5, -1 ], [ 3, -4, -5, 5, -5, -1 ], [ 3, -4, -6, 5, -5, -1 ], [ 3, -3, -5, 5, -5, -1 ] ], 1 ] - ], - [ - [ [ [ 1, -4, -5, 5, -5, -1 ], [ 3, -4, -5, 5, -5, -1 ], [ 3, -3, -6, 5, -5, -1 ], [ 3, -3, -5, 5, -5, -1 ] ], 1.75 ] - ], - [ - [ [ [ 1, -4, -5, 5, -5, -1 ], [ 3, -4, -5, 5, -5, -1 ], [ 4, -5, -5, 5, -5, -1 ], [ 3, -3, -5, 5, -5, -1 ] ], 1.375 ], - [ [ [ 1, -4, -5, 5, -5, -1 ], [ 3, -4, -5, 5, -5, -1 ], [ 4, -5, -5, 5, -5, -1 ], [ 4, -4, -6, 5, -5, -1 ] ], 0.75 ] - ], - [ - [ [ [ 1, -4, -5, 5, -5, -1 ], [ 3, -4, -5, 5, -5, -1 ], [ 3, -3, -5, 5, -5, -1 ], [ 4, -4, -6, 5, -5, -1 ] ], 1.5 ] - ], - [ - [ [ [ 1, -4, -5, 5, -5, -1 ], [ 3, -4, -5, 5, -5, -1 ], [ 3, -4, -5, 6, -5, -1 ], [ 4, -4, -6, 5, -5, -1 ] ], 1.375 ], - [ [ [ 1, -4, -5, 5, -5, -1 ], [ 3, -5, -5, 5, -5, -1 ], [ 3, -4, -5, 6, -5, -1 ], [ 4, -4, -6, 5, -5, -1 ] ], 1.375 ], - [ [ [ 1, -4, -5, 5, -5, -1 ], [ 3, -5, -5, 5, -5, -1 ], [ 3, -4, -5, 6, -5, -1 ], [ 2, -4, -5, 5, -5, 0 ] ], 1.25 ] - ], - [ - [ [ [ 1, -5, -5, 5, -5, 0 ], [ 3, -5, -5, 5, -5, -1 ], [ 3, -4, -5, 6, -5, -1 ], [ 2, -4, -5, 5, -5, 0 ] ], 0.5 ], - [ [ [ 1, -5, -5, 5, -5, 0 ], [ 3, -5, -5, 5, -5, -1 ], [ 4, -4, -5, 4, -5, 0 ], [ 2, -4, -5, 5, -5, 0 ] ], 1 ] - ], - [ - [ [ [ 2, -5, -5, 4, -5, 0 ], [ 3, -5, -5, 5, -5, -1 ], [ 4, -4, -5, 4, -5, 0 ], [ 2, -4, -5, 5, -5, 0 ] ], 1.375 ], - [ [ [ 2, -5, -5, 4, -5, 0 ], [ 2, -3, -5, 4, -5, 0 ], [ 4, -4, -5, 4, -5, 0 ], [ 2, -4, -5, 5, -5, 0 ] ], 1 ] - ], - [ - [ [ [ 2, -5, -5, 4, -5, 0 ], [ 2, -3, -5, 4, -5, 0 ], [ 4, -4, -5, 4, -5, 0 ], [ 3, -4, -5, 4, -5, 0 ] ], 1.625 ] - ], - [ - [ [ [ 1, -4, -5, 4, -5, 0 ], [ 2, -3, -5, 4, -5, 0 ], [ 4, -4, -5, 4, -5, 0 ], [ 3, -4, -5, 4, -5, 0 ] ], 1.375 ], - [ [ [ 1, -4, -5, 4, -5, 0 ], [ 2, -3, -5, 4, -5, 0 ], [ 4, -4, -5, 4, -5, 0 ], [ 2, -2, -5, 4, -5, 0 ] ], 1.75 ] - ], - [ - [ [ [ 2, -4, -5, 3, -5, 0 ], [ 2, -3, -5, 4, -5, 0 ], [ 4, -4, -5, 4, -5, 0 ], [ 2, -2, -5, 4, -5, 0 ] ], 1.375 ], - [ [ [ 2, -4, -5, 3, -5, 0 ], [ 3, -4, -6, 4, -5, 0 ], [ 4, -4, -5, 4, -5, 0 ], [ 2, -2, -5, 4, -5, 0 ] ], 1.25 ], - [ [ [ 2, -4, -5, 3, -5, 0 ], [ 3, -4, -6, 4, -5, 0 ], [ 4, -4, -5, 4, -5, 0 ], [ 3, -4, -4, 4, -5, 0 ] ], 0.75 ] - ], - [ - [ [ [ 2, -4, -5, 3, -5, 0 ], [ 3, -4, -6, 4, -5, 0 ], [ 4, -4, -6, 4, -5, 0 ], [ 3, -4, -4, 4, -5, 0 ] ], 1.125 ], - [ [ [ 2, -4, -5, 3, -5, 0 ], [ 3, -4, -6, 4, -5, 0 ], [ 4, -4, -6, 4, -5, 0 ], [ 4, -4, -6, 3, -5, 0 ] ], 0.875 ] - ], - [ - [ [ [ 2, -4, -5, 3, -5, 0 ], [ 3, -4, -7, 4, -5, 0 ], [ 4, -4, -6, 4, -5, 0 ], [ 4, -4, -6, 3, -5, 0 ] ], 1.375 ], - [ [ [ 3, -5, -6, 3, -5, 0 ], [ 3, -4, -7, 4, -5, 0 ], [ 4, -4, -6, 4, -5, 0 ], [ 4, -4, -6, 3, -5, 0 ] ], 1.75 ] - ], - [ - [ [ [ 3, -5, -6, 3, -5, 0 ], [ 3, -4, -7, 4, -5, 0 ], [ 5, -5, -7, 4, -5, 0 ], [ 4, -4, -6, 3, -5, 0 ] ], 1.125 ], - [ [ [ 3, -5, -6, 3, -5, 0 ], [ 3, -4, -7, 4, -5, 0 ], [ 5, -5, -7, 4, -5, 0 ], [ 5, -5, -7, 3, -5, 0 ] ], 1.5 ] - ], - [ - [ [ [ 3, -5, -6, 3, -5, 0 ], [ 3, -4, -7, 4, -5, 0 ], [ 5, -5, -7, 4, -5, 0 ], [ 4, -5, -6, 4, -5, 0 ] ], 0.625 ], - [ [ [ 3, -5, -6, 3, -5, 0 ], [ 5, -5, -6, 2, -5, 0 ], [ 5, -5, -7, 4, -5, 0 ], [ 4, -5, -6, 4, -5, 0 ] ], 1.375 ], - [ [ [ 3, -5, -6, 3, -5, 0 ], [ 5, -5, -6, 2, -5, 0 ], [ 5, -4, -6, 3, -5, 0 ], [ 4, -5, -6, 4, -5, 0 ] ], 1.375 ] - ], - [ - [ [ [ 3, -5, -6, 3, -5, 0 ], [ 5, -5, -6, 2, -5, 0 ], [ 5, -4, -6, 3, -5, 0 ], [ 5, -5, -6, 3, -5, 0 ] ], 0.75 ] - ], - [ - [ [ [ 3, -5, -6, 3, -5, 0 ], [ 5, -5, -6, 2, -5, 0 ], [ 5, -4, -6, 3, -5, 0 ], [ 6, -5, -6, 2, -5, 0 ] ], 0.5 ], - [ [ [ 4, -5, -6, 2, -5, 0 ], [ 5, -5, -6, 2, -5, 0 ], [ 5, -4, -6, 3, -5, 0 ], [ 6, -5, -6, 2, -5, 0 ] ], 1.125 ] - ], - [ - [ [ [ 4, -5, -6, 2, -5, 0 ], [ 5, -5, -6, 2, -5, 0 ], [ 5, -4, -6, 3, -5, 0 ], [ 4, -4, -6, 3, -5, 0 ] ], 1.25 ], - [ [ [ 4, -5, -6, 2, -5, 0 ], [ 4, -4, -7, 3, -5, 0 ], [ 5, -4, -6, 3, -5, 0 ], [ 4, -4, -6, 3, -5, 0 ] ], 1.25 ], - [ [ [ 4, -5, -6, 2, -5, 0 ], [ "Rest" ], [ 5, -4, -6, 3, -5, 0 ], [ 4, -4, -6, 3, -5, 0 ] ], 0.5 ], - [ [ [ "Rest" ], [ "Rest" ], [ 5, -4, -6, 3, -5, 0 ], [ 4, -4, -6, 3, -5, 0 ] ], 1.75 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 4, -4, -6, 3, -5, 0 ] ], 1.125 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 7.25 ] - ] - ] -], -"last_changes": -[ - [ [ 3, -5, -6, 3, -5, 0 ], [ 5, -5, -6, 2, -5, 0 ], [ 5, -4, -6, 3, -5, 0 ], [ 5, -5, -6, 3, -5, 0 ] ], - [ [ 3, -5, -6, 3, -5, 0 ], [ 5, -5, -6, 2, -5, 0 ], [ 5, -4, -6, 3, -5, 0 ], [ 6, -5, -6, 2, -5, 0 ] ], - [ [ 4, -5, -6, 2, -5, 0 ], [ 5, -5, -6, 2, -5, 0 ], [ 5, -4, -6, 3, -5, 0 ], [ 6, -5, -6, 2, -5, 0 ] ], - [ [ 4, -5, -6, 2, -5, 0 ], [ 5, -5, -6, 2, -5, 0 ], [ 5, -4, -6, 3, -5, 0 ], [ 4, -4, -6, 3, -5, 0 ] ], - [ [ 4, -5, -6, 2, -5, 0 ], [ 4, -4, -7, 3, -5, 0 ], [ 5, -4, -6, 3, -5, 0 ], [ 4, -4, -6, 3, -5, 0 ] ] -], -"cur_uid": "75316bf0", -"ref_uid": "55bd25a1", -"order_seed": 144453, -"dur_seed": 681001, -"motifs_seed": 933698, -"entrances_probs_vals": [ 0, 0, 0, 0.41, 1.84, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 0.41, 1.84, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 0.41, 1.84, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2430, -293 ], [ -869, 1211 ], [ -832, 1285 ], [ -702, 1211 ] ], -"step_probs_vals": [ -1200, 1200, 0.0020576131687243, 0.068181818181818, 0.074074074074074, 0.0625, 0.20576131687243, 0.0625, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61316872427983, 0, 0.98971193415638, 0 ], -"passages_weights": [ 0.48, 0.46, 0.48, 1, 1 ], -"hd_exp": 9, -"hd_invert": 0, -"order": -[ - [ [ 1 ], [ 2, 3, 0 ], [ ] ], - [ [ 0, 2 ], [ 3, 1 ], [ ] ], - [ [ 1, 0 ], [ 2, 3 ], [ ] ], - [ [ 1, 3 ], [ 0, 2 ], [ ] ], - [ [ 0, 2 ], [ 3, 1 ], [ ] ], - [ [ 3, 0 ], [ 1, 2 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 3 ], [ 1, 2, 0 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 1 ], [ 0, 2, 3 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 0, 2 ], [ 3, 1 ], [ ] ], - [ [ 0, 1 ], [ 3, 2 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 2, 3 ], [ 1, 0 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 1 ], [ 2, 0, 3 ], [ ] ], - [ [ 3 ], [ 1, 2, 0 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 0, 1 ], [ 3, 2 ], [ ] ], - [ [ 1, 0 ], [ 2, 3 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 3 ], [ 0, 2, 1 ], [ ] ], - [ [ 1 ], [ 0, 3, 2 ], [ ] ], - [ [ 1 ], [ 2, 3, 0 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 0, 1 ], [ 3, 2 ], [ ] ], - [ [ 2, 0 ], [ 3, 1 ], [ ] ], - [ [ 3 ], [ 1, 0, 2 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 1, 0 ], [ 2, 3 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 0, 3 ], [ 1, 2 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 2, 3 ], [ 1, 0 ], [ ] ], - [ [ 1 ], [ 3, 2, 0 ], [ ] ], - [ [ 2, 0, 3 ], [ 1 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 1 ], [ 3, 2, 0 ], [ ] ], - [ [ 2 ], [ 0, 3, 1 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 3 ], [ 1, 0, 2 ], [ ] ], - [ [ 3 ], [ 1, 0, 2 ], [ ] ], - [ [ 1, 3 ], [ 2, 0 ], [ ] ], - [ [ 1, 0 ], [ 2, 3 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 1 ], [ 0, 3, 2 ], [ ] ], - [ [ 0, 1 ], [ 2, 3 ], [ ] ], - [ [ 1, 0 ], [ 3, 2 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 3, 2 ], [ 1, 0 ], [ ] ], - [ [ 2 ], [ 1, 3, 0 ], [ ] ], - [ [ 0, 1 ], [ 3, 2 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 3 ], [ 1, 0, 2 ], [ ] ], - [ [ 1 ], [ 0, 2, 3 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ], - [ [ 2, 0 ], [ 1, 3 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 3 ], [ 1, 2, 0 ], [ ] ], - [ [ 2, 1 ], [ 0, 3 ], [ ] ], - [ [ 1 ], [ 0, 2, 3 ], [ ] ], - [ [ 3 ], [ 0, 2, 1 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 3, 2 ], [ 1, 0 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 0, 3 ], [ 2, 1 ], [ ] ], - [ [ 3 ], [ 1, 2, 0 ], [ ] ], - [ [ 2, 1 ], [ 0, 3 ], [ ] ], - [ [ 3, 2 ], [ 0, 1 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 0, 1 ], [ 2, 3 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 3, 2 ], [ 0, 1 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 2, 1 ], [ 0, 3 ], [ ] ], - [ [ 2 ], [ 0, 1, 3 ], [ ] ], - [ [ 0, 1 ], [ 2, 3 ], [ ] ], - [ [ 3, 2 ], [ 1, 0 ], [ ] ], - [ [ 1, 0 ], [ 2, 3 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 0, 2 ], [ 3, 1 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 100, 100 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/781442dc/781442dc_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3/781442dc/781442dc_code.scd deleted file mode 100644 index c194eef..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/781442dc/781442dc_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/781442dc/781442dc_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3/781442dc/781442dc_mus_model.json deleted file mode 100644 index d2de366..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/781442dc/781442dc_mus_model.json +++ /dev/null @@ -1,117 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 0.25 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 0.5 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 1, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0.125 ], - [ [ [ 0, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.375 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 0, 1 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 1 ], [ -1, 0, 0, 0, 1, 1 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 0, 1 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 1 ], [ -1, 0, 0, 0, 1, 1 ], [ -1, 0, 0, 1, 0, 1 ], [ 0, -1, 0, 0, 0, 1 ] ], 0.25 ], - [ [ [ 0, 0, 0, 0, 0, 1 ], [ -1, 0, 0, 0, 1, 1 ], [ -1, 0, 0, 1, 0, 1 ], [ 0, 0, 0, 0, -1, 1 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 0, 1 ], [ -1, 0, 0, 0, 1, 1 ], [ -1, 0, 0, 0, 0, 2 ], [ 0, 0, 0, 0, -1, 1 ] ], 0.875 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 1 ], [ -1, 0, 0, 0, 1, 1 ], [ -1, 0, 0, 0, 0, 2 ], [ "Rest" ] ], 0 ], - [ [ [ 0, -1, 0, 0, 0, 2 ], [ -1, 0, 0, 0, 1, 1 ], [ -1, 0, 0, 0, 0, 2 ], [ "Rest" ] ], 0 ], - [ [ [ 0, -1, 0, 0, 0, 2 ], [ -1, 0, -1, 0, 0, 2 ], [ -1, 0, 0, 0, 0, 2 ], [ "Rest" ] ], 0.25 ], - [ [ [ -1, 0, 0, 0, 1, 2 ], [ -1, 0, -1, 0, 0, 2 ], [ -1, 0, 0, 0, 0, 2 ], [ "Rest" ] ], 0.25 ], - [ [ [ -1, 0, 1, 0, 0, 2 ], [ -1, 0, -1, 0, 0, 2 ], [ -1, 0, 0, 0, 0, 2 ], [ "Rest" ] ], 0.25 ], - [ [ [ -2, 0, 1, 0, 0, 2 ], [ -1, 0, -1, 0, 0, 2 ], [ -1, 0, 0, 0, 0, 2 ], [ "Rest" ] ], 1.375 ] - ], - [ - [ [ [ -2, 0, 1, 0, 0, 2 ], [ -1, 0, -1, 0, 0, 2 ], [ -1, 0, 0, 0, 0, 2 ], [ 0, 0, 0, 0, -1, 1 ] ], 0.5 ], - [ [ [ -2, 0, 1, 0, 0, 2 ], [ -1, 0, 1, 0, 0, 1 ], [ -1, 0, 0, 0, 0, 2 ], [ 0, 0, 0, 0, -1, 1 ] ], 0 ], - [ [ [ -2, 0, 1, 0, 0, 2 ], [ -1, 0, 1, 0, 0, 1 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 1 ] ], 0.625 ], - [ [ [ -2, 0, 1, 0, 0, 2 ], [ 0, 0, -1, 0, -1, 1 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 1 ] ], 0 ], - [ [ [ -2, 0, 1, 0, 0, 2 ], [ 0, 0, -1, 0, -1, 1 ], [ 1, -1, 0, 0, -1, 1 ], [ 0, 0, 0, 0, -1, 1 ] ], 1 ] - ], - [ - [ [ [ -1, 1, 0, 0, -1, 1 ], [ 0, 0, -1, 0, -1, 1 ], [ 1, -1, 0, 0, -1, 1 ], [ 0, 0, 0, 0, -1, 1 ] ], 0 ], - [ [ [ -1, 1, 0, 0, -1, 1 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 1 ], [ 0, 0, 0, 0, -1, 1 ] ], 0.625 ], - [ [ [ 0, -1, 1, 0, -1, 1 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 1 ], [ 0, 0, 0, 0, -1, 1 ] ], 0.625 ], - [ [ [ 0, 0, -1, 0, -1, 1 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 1 ], [ 0, 0, 0, 0, -1, 1 ] ], 0 ], - [ [ [ 0, 0, -1, 0, -1, 1 ], [ 1, -1, 0, -1, -1, 1 ], [ 1, -1, 0, 0, -1, 1 ], [ 0, 0, 0, 0, -1, 1 ] ], 1.125 ] - ], - [ - [ [ [ 0, 0, -1, 0, -1, 1 ], [ 1, -1, 0, -1, -1, 1 ], [ 1, -1, 0, 0, -1, 1 ], [ "Rest" ] ], 0 ], - [ [ [ 0, 0, -1, 0, -1, 1 ], [ 1, -1, 0, -1, -1, 1 ], [ 1, -1, 0, -1, -1, 2 ], [ "Rest" ] ], 0.625 ], - [ [ [ 0, 0, -1, 0, -1, 1 ], [ 1, -1, 0, -1, -1, 1 ], [ 2, -1, -1, -1, -1, 1 ], [ "Rest" ] ], 0.5 ], - [ [ [ 0, 0, -1, 0, -1, 1 ], [ 1, -1, 0, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 1 ], [ "Rest" ] ], 1.375 ] - ], - [ - [ [ [ 0, 0, 0, -1, 0, 1 ], [ 1, -1, 0, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 1 ], [ "Rest" ] ], 0 ], - [ [ [ 0, 0, 0, -1, 0, 1 ], [ 1, -1, 0, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 1 ], [ 1, -1, 1, -1, -1, 1 ] ], 0.375 ], - [ [ [ 2, -1, 0, -2, -1, 1 ], [ 1, -1, 0, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 1 ], [ 1, -1, 1, -1, -1, 1 ] ], 0 ], - [ [ [ 2, -1, 0, -2, -1, 1 ], [ 1, -1, 0, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 1 ], [ 1, 0, -1, -1, -1, 1 ] ], 1 ] - ], - [ - [ [ [ 1, 0, 0, -1, -2, 1 ], [ 1, -1, 0, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 1 ], [ 1, 0, -1, -1, -1, 1 ] ], 0 ], - [ [ [ 1, 0, 0, -1, -2, 1 ], [ 0, 0, 1, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 1 ], [ 1, 0, -1, -1, -1, 1 ] ], 0.625 ], - [ [ [ 1, 0, 0, -1, -2, 1 ], [ 1, 0, -2, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 1 ], [ 1, 0, -1, -1, -1, 1 ] ], 0.25 ], - [ [ [ 1, 0, 0, -1, -2, 1 ], [ 0, 1, -1, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 1 ], [ 1, 0, -1, -1, -1, 1 ] ], 1.375 ] - ], - [ - [ [ [ 1, 1, -1, -1, -1, 0 ], [ 0, 1, -1, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 1 ], [ 1, 0, -1, -1, -1, 1 ] ], 0.375 ], - [ [ [ 0, 0, 0, -2, -1, 1 ], [ 0, 1, -1, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 1 ], [ 1, 0, -1, -1, -1, 1 ] ], 0.375 ], - [ [ [ -1, 1, -1, -1, -1, 1 ], [ 0, 1, -1, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 1 ], [ 1, 0, -1, -1, -1, 1 ] ], 1.25 ] - ], - [ - [ [ [ -1, 1, -1, -1, -1, 1 ], [ 0, 1, -1, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 1 ], [ 0, 0, 0, -1, -1, 2 ] ], 0 ], - [ [ [ -1, 1, -1, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 0 ], [ 1, 0, 0, -1, -1, 1 ], [ 0, 0, 0, -1, -1, 2 ] ], 0 ], - [ [ [ 0, 0, 0, -1, -1, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 1, 0, 0, -1, -1, 1 ], [ 0, 0, 0, -1, -1, 2 ] ], 0.25 ], - [ [ [ 0, 0, 0, -1, -1, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 1, 0, 0, -1, -1, 1 ], [ 0, 0, 0, 0, -1, 1 ] ], 0.625 ], - [ [ [ 0, 0, 0, -1, -1, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 1, 0, 0, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 2 ] ], 1.375 ], - [ [ [ 0, 0, 0, -1, -1, 0 ], [ "Rest" ], [ 1, 0, 0, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 2 ] ], 0 ], - [ [ [ 0, 0, 0, -1, -1, 0 ], [ "Rest" ], [ 1, 0, 0, -1, -1, 1 ], [ "Rest" ] ], 0 ], - [ [ [ 0, 0, 0, -1, -1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 5.625 ] - ] - ] -], -"last_changes": -[ - [ [ -1, 1, -1, -1, -1, 1 ], [ 0, 1, -1, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 1 ], [ 0, 0, 0, -1, -1, 2 ] ], - [ [ -1, 1, -1, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 0 ], [ 1, 0, 0, -1, -1, 1 ], [ 0, 0, 0, -1, -1, 2 ] ], - [ [ 0, 0, 0, -1, -1, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 1, 0, 0, -1, -1, 1 ], [ 0, 0, 0, -1, -1, 2 ] ], - [ [ 0, 0, 0, -1, -1, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 1, 0, 0, -1, -1, 1 ], [ 0, 0, 0, 0, -1, 1 ] ], - [ [ 0, 0, 0, -1, -1, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 1, 0, 0, -1, -1, 1 ], [ 1, 0, 0, -1, -1, 2 ] ] -], -"cur_uid": "781442dc", -"ref_uid": "nil", -"order_seed": 479669, -"dur_seed": 398026, -"motifs_seed": 801394, -"entrances_probs_vals": [ 0.43, 0, 0, 0, 0.85164835164835, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 1, 0, 0.99206349206349, 0.16483516483516, 0.66, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 1, 0, 0.95238095238095, 0, 1.043956043956, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -1983.9009287926, 1100 ], [ -999, 1322.600619195 ], [ -14.860681114551, 1676 ], [ 78.018575851393, 1694 ] ], -"step_probs_vals": [ 0, 1200, 0, 0.5, 0.076131687242798, 0.91477272727273, 0.17489711934156, 0, 0.57818930041152, 0, 1, 0 ], -"passages_weights": [ 0.54, 0.47, 0.52, 0.57, 0.58 ], -"hd_exp": -0.22, -"hd_invert": 0, -"order": -[ - [ [ 3, 1 ], [ 2, 0, 0, 2 ], [ ] ], - [ [ 0 ], [ 3, 1, 2, 3, 2 ], [ ] ], - [ [ 2 ], [ 0, 1, 0, 0, 0 ], [ 3 ] ], - [ [ 0, 3 ], [ 1, 2, 1, 2 ], [ ] ], - [ [ 2, 3 ], [ 0, 1, 0, 0, 1 ], [ ] ], - [ [ 1, 0 ], [ 2, 2, 2 ], [ 3 ] ], - [ [ 1, 2 ], [ 0, 3, 0, 3 ], [ ] ], - [ [ 3, 2 ], [ 0, 1, 1, 1 ], [ ] ], - [ [ 1, 2, 3 ], [ 0, 0, 0 ], [ ] ], - [ [ 2 ], [ 3, 1, 0, 3, 3 ], [ ] ] -], -"sus_weights": [ 0.44, 0.41, 0.28 ], -"order_size": [ 10, 10 ], -"passages_size": [ 2, 4 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/7c2de94c/7c2de94c_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3/7c2de94c/7c2de94c_code.scd deleted file mode 100644 index dc13462..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/7c2de94c/7c2de94c_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array1) - hsArrayToCents.value(array2); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - if(pDistance < 0, {stepFunc.value(pDistance)}, {0}); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength - minMotifLength).rand + minMotifLength).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength - minProgLength).rand + minProgLength).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[-3, 0, 0, 0, 0, 0], [-3, 0, 0, 0, 0, 0], [-3, 0, 0, 0, 0, 0], [-3, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[-3, 0, 0, 0, 0, 0], [-3, 0, 0, 0, 0, 0], [-3, 0, 0, 0, 0, 0], [-3, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/7c2de94c/7c2de94c_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3/7c2de94c/7c2de94c_mus_model.json deleted file mode 100644 index 37e7285..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/7c2de94c/7c2de94c_mus_model.json +++ /dev/null @@ -1,163 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ] ], 0.125 ], - [ [ [ "Rest" ], [ "Rest" ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 1.125 ], - [ [ [ "Rest" ], [ 1, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 1.125 ], - [ [ [ -1, 0, 1, 0, 0, 1 ], [ 1, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0.875 ] - ], - [ - [ [ [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0.375 ] - ], - [ - [ [ [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 1, 0, 0, -1, 0, 0 ], [ 3, -1, 0, -1, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ] ], 0.75 ] - ], - [ - [ [ [ 0, -1, 0, 1, 0, 0 ], [ 3, -1, 0, -1, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ] ], 0.375 ] - ], - [ - [ [ [ 0, -1, 0, 1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ] ], 0.125 ] - ], - [ - [ [ [ 0, -1, 0, 1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ] ], 0.75 ] - ], - [ - [ [ [ 0, -1, 0, 1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, -1, 1, 0, 0 ] ], 0.375 ] - ], - [ - [ [ [ 0, -1, 0, 0, 0, -1 ], [ 2, 0, 0, -1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, -1, 1, 0, 0 ] ], 0.5 ] - ], - [ - [ [ [ 0, -1, 0, 0, 0, -1 ], [ 2, -1, -1, 1, 0, -1 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, -1, 1, 0, 0 ] ], 0 ] - ], - [ - [ [ [ 0, -1, 0, 0, 0, -1 ], [ 2, -1, -1, 1, 0, -1 ], [ 2, 0, 0, 0, 0, -1 ], [ 1, -1, -1, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, -1, 0, 0, 0, -1 ], [ 3, -1, 0, 0, 0, -2 ], [ 2, 0, 0, 0, 0, -1 ], [ 1, -1, -1, 1, 0, 0 ] ], 0.5 ] - ], - [ - [ [ [ 0, -1, 0, 0, 0, -1 ], [ 2, -1, 1, 0, 0, -1 ], [ 2, 0, 0, 0, 0, -1 ], [ 1, -1, -1, 1, 0, 0 ] ], 0.875 ] - ], - [ - [ [ [ 0, -1, 0, 0, 0, -1 ], [ 2, -1, 1, 0, 0, -1 ], [ 2, 0, 0, 0, 0, -1 ], [ 3, -1, 0, 0, 0, -2 ] ], 1.125 ] - ], - [ - [ [ [ 0, -1, 0, 0, 0, -1 ], [ 2, -1, 1, 0, 0, -1 ], [ 3, -1, 1, 0, 0, -2 ], [ 3, -1, 0, 0, 0, -2 ] ], 0.625 ] - ], - [ - [ [ [ 1, -1, 1, 0, 0, -2 ], [ 2, -1, 1, 0, 0, -1 ], [ 3, -1, 1, 0, 0, -2 ], [ 3, -1, 0, 0, 0, -2 ] ], 0.125 ] - ], - [ - [ [ [ 1, -1, 1, 0, 0, -2 ], [ 2, -1, 1, 0, 0, -1 ], [ 3, -1, 1, 0, 0, -2 ], [ 3, -1, 1, -1, 0, -1 ] ], 0.5 ] - ], - [ - [ [ [ 1, -1, 1, 0, 0, -2 ], [ 2, -1, 1, 0, 0, -1 ], [ 3, -1, 1, 0, 0, -2 ], [ 2, -1, 2, 0, 0, -1 ] ], 0.25 ] - ], - [ - [ [ [ 1, -1, 1, 0, 0, -2 ], [ 2, -1, 1, 0, 0, -1 ], [ -1, 0, 1, 0, 0, -1 ], [ 2, -1, 2, 0, 0, -1 ] ], 0.75 ] - ], - [ - [ [ [ 1, -1, 1, 0, 0, -2 ], [ 2, -1, 1, 0, 0, -1 ], [ -1, 0, 2, 0, 0, -1 ], [ 2, -1, 2, 0, 0, -1 ] ], 0.125 ] - ], - [ - [ [ [ 1, -1, 1, 0, 0, -2 ], [ 2, -1, 1, 0, 0, -1 ], [ 3, -1, 0, 0, 0, -2 ], [ 2, -1, 2, 0, 0, -1 ] ], 0.625 ] - ], - [ - [ [ [ 1, -1, 1, 0, 0, -2 ], [ 2, -1, 1, 0, 0, -1 ], [ 3, -1, 1, 0, 0, -2 ], [ 2, -1, 2, 0, 0, -1 ] ], 1 ] - ], - [ - [ [ [ 1, -1, 1, 0, 0, -2 ], [ 2, -1, 1, 0, 0, -1 ], [ 3, -1, 1, 0, 0, -2 ], [ 3, -1, 0, 0, 0, -2 ] ], 0.125 ] - ], - [ - [ [ [ 1, -1, 1, 0, 0, -2 ], [ 4, -1, 0, -1, 0, -2 ], [ 3, -1, 1, 0, 0, -2 ], [ 3, -1, 0, 0, 0, -2 ] ], 0.5 ] - ], - [ - [ [ [ 1, -1, 1, 0, 0, -2 ], [ 0, -1, 0, 0, 0, -1 ], [ 3, -1, 1, 0, 0, -2 ], [ 3, -1, 0, 0, 0, -2 ] ], 0.625 ] - ], - [ - [ [ [ 1, -1, 0, 1, 0, -2 ], [ 0, -1, 0, 0, 0, -1 ], [ 3, -1, 1, 0, 0, -2 ], [ 3, -1, 0, 0, 0, -2 ] ], 0.75 ] - ], - [ - [ [ [ 1, -1, 0, 1, 0, -2 ], [ 0, -1, 0, 0, 0, -1 ], [ 3, -1, 0, 1, -1, -2 ], [ 3, -1, 0, 0, 0, -2 ] ], 0.5 ] - ], - [ - [ [ [ 1, -1, 0, 1, 0, -2 ], [ 1, -2, 0, 1, 0, -2 ], [ 3, -1, 0, 1, -1, -2 ], [ 3, -1, 0, 0, 0, -2 ] ], 1 ] - ], - [ - [ [ [ 1, -1, 0, 1, 0, -2 ], [ 1, -2, 0, 1, 0, -2 ], [ 3, -1, -1, 1, 0, -2 ], [ 3, -1, 0, 0, 0, -2 ] ], 0.125 ] - ], - [ - [ [ [ 1, -1, 0, 1, 0, -2 ], [ 1, -2, 0, 1, 0, -2 ], [ 0, -1, 0, 0, 0, -1 ], [ 3, -1, 0, 0, 0, -2 ] ], 0.875 ], - [ [ [ 1, -1, 0, 1, 0, -2 ], [ 1, -2, 0, 1, 0, -2 ], [ 0, -1, 0, 0, 0, -1 ], [ "Rest" ] ], 0.375 ], - [ [ [ 1, -1, 0, 1, 0, -2 ], [ 1, -2, 0, 1, 0, -2 ], [ "Rest" ], [ "Rest" ] ], 0.5 ], - [ [ [ 1, -1, 0, 1, 0, -2 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0.625 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 6.5 ] - ] - ] -], -"last_changes": -[ - [ [ 1, -1, 0, 1, 0, -2 ], [ 0, -1, 0, 0, 0, -1 ], [ 3, -1, 1, 0, 0, -2 ], [ 3, -1, 0, 0, 0, -2 ] ], - [ [ 1, -1, 0, 1, 0, -2 ], [ 0, -1, 0, 0, 0, -1 ], [ 3, -1, 0, 1, -1, -2 ], [ 3, -1, 0, 0, 0, -2 ] ], - [ [ 1, -1, 0, 1, 0, -2 ], [ 1, -2, 0, 1, 0, -2 ], [ 3, -1, 0, 1, -1, -2 ], [ 3, -1, 0, 0, 0, -2 ] ], - [ [ 1, -1, 0, 1, 0, -2 ], [ 1, -2, 0, 1, 0, -2 ], [ 3, -1, -1, 1, 0, -2 ], [ 3, -1, 0, 0, 0, -2 ] ], - [ [ -2, -1, 0, 1, 0, -2 ], [ -2, -2, 0, 1, 0, -2 ], [ -2, -1, 0, 0, 0, -1 ], [ -2, -1, 0, 0, 0, -2 ] ] -], -"cur_uid": "7c2de94c", -"ref_uid": "5201b8af", -"order_seed": 869423, -"dur_seed": 680450, -"motifs_seed": 533263, -"entrances_probs_vals": [ 0, 0, 0, 0, 1.2087912087912, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 0, 1.2087912087912, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 0, 1.2087912087912, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2169.6594427245, 338 ], [ -2522.600619195, 1453 ], [ -1649.5356037152, 1676 ], [ -2894.1176470588, 1694 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.063786008230453, 0.92613636363636, 0.12757201646091, 0, 0.54732510288066, 0, 0.71604938271605, 0, 1, 0 ], -"passages_weights": [ 1, 0, 0.2, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 2, 0, 3 ], [ 1 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ] -], -"sus_weights": [ 0, 0, 0.61 ], -"order_size": [ 30, 30 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/7e230015/7e230015_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3/7e230015/7e230015_code.scd deleted file mode 100644 index 7c7b526..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/7e230015/7e230015_code.scd +++ /dev/null @@ -1,975 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-10); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/7e230015/7e230015_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3/7e230015/7e230015_mus_model.json deleted file mode 100644 index 7948320..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/7e230015/7e230015_mus_model.json +++ /dev/null @@ -1,532 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 0, -1, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 0, -1, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 0, -1, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 0, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 0, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ] ], 1 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 0, 0, 0, 0, 0 ], [ -1, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ] ], 1 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ -1, 0, 1, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 0, 0, 0, 0, 0 ], [ -1, 0, 1, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 0, 0, 0, 0, 0 ], [ -1, 0, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 1, 1, 0, 0, 0 ], [ -1, 0, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 1, 1, 0, 0, 0 ], [ -1, 0, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 1, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 0, 1, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 0, 1, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 1, -1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 0, 1, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ -1, 0, 2, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 0, 1, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ], [ -1, 0, 2, 1, 0, 0 ], [ -1, 0, 2, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 0, 1, 0, 0, 0 ], [ 0, -1, 2, 0, 0, 0 ], [ -1, 0, 2, 1, 0, 0 ], [ -1, 0, 2, 0, 0, 0 ] ], 1 ], - [ [ [ -1, -1, 2, 0, 0, 0 ], [ 0, -1, 2, 0, 0, 0 ], [ -1, 0, 2, 1, 0, 0 ], [ -1, 0, 2, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, -1, 2, 1, 0, 0 ], [ 0, -1, 2, 0, 0, 0 ], [ -1, 0, 2, 1, 0, 0 ], [ -1, 0, 2, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, -1, 2, 1, 0, 0 ], [ -1, 1, 2, 0, 0, 0 ], [ -1, 0, 2, 1, 0, 0 ], [ -1, 0, 2, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, -1, 2, 1, 0, 0 ], [ -1, 1, 2, 0, 0, 0 ], [ -1, 0, 2, 1, 0, 0 ], [ -2, 0, 2, 1, 0, 0 ] ], 1 ], - [ [ [ -2, 1, 2, 1, 0, 0 ], [ -1, 1, 2, 0, 0, 0 ], [ -1, 0, 2, 1, 0, 0 ], [ -2, 0, 2, 1, 0, 0 ] ], 1 ], - [ [ [ -2, 1, 2, 1, 0, 0 ], [ -1, -1, 2, 1, 0, 0 ], [ -1, 0, 2, 1, 0, 0 ], [ -2, 0, 2, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 2, 1, 0, 0 ], [ -1, -1, 2, 1, 0, 0 ], [ -1, 0, 2, 1, 0, 0 ], [ -1, -1, 1, 1, 0, 0 ] ], 1 ], - [ [ [ -1, -1, 3, 1, 0, 0 ], [ -1, -1, 2, 1, 0, 0 ], [ -1, 0, 2, 1, 0, 0 ], [ -1, -1, 1, 1, 0, 0 ] ], 1 ], - [ [ [ -1, -1, 3, 1, 0, 0 ], [ -1, -1, 2, 1, 0, 0 ], [ 0, -1, 1, 1, 0, 0 ], [ -1, -1, 1, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, -1, 3, 1, 0, 0 ], [ -1, -1, 2, 1, 0, 0 ], [ 0, -1, 1, 1, 0, 0 ], [ -1, -1, 1, 1, 0, 1 ] ], 1 ], - [ [ [ -1, -1, 3, 1, 0, 0 ], [ 0, -2, 1, 1, 0, 0 ], [ 0, -1, 1, 1, 0, 0 ], [ -1, -1, 1, 1, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -1, -1, 3, 1, 0, 0 ], [ 0, -2, 1, 1, 0, 0 ], [ 0, -2, 1, 1, 0, 1 ], [ -1, -1, 1, 1, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -1, -1, 3, 1, 0, 0 ], [ 0, -2, 1, 1, 0, 0 ], [ 0, -2, 1, 1, 0, 1 ], [ 1, -3, 1, 1, 0, 0 ] ], 1 ], - [ [ [ 0, -2, 2, 1, 0, 0 ], [ 0, -2, 1, 1, 0, 0 ], [ 0, -2, 1, 1, 0, 1 ], [ 1, -3, 1, 1, 0, 0 ] ], 1 ], - [ [ [ 0, -2, 2, 1, 0, 0 ], [ 0, -2, 1, 1, 0, 0 ], [ 0, -2, 1, 2, 0, 0 ], [ 1, -3, 1, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, -2, 2, 1, 0, 0 ], [ 0, -2, 1, 1, 0, 0 ], [ 0, -2, 1, 2, 0, 0 ], [ 1, -2, 1, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, -2, 2, 1, 0, 0 ], [ 0, -2, 1, 1, 0, 0 ], [ 0, -2, 1, 2, 0, 0 ], [ 0, -2, 0, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, -2, 1, 2, 0, 0 ], [ 0, -2, 1, 1, 0, 0 ], [ 0, -2, 1, 2, 0, 0 ], [ 0, -2, 0, 2, 0, 0 ] ], 1 ], - [ [ [ -1, -2, 1, 2, 0, 0 ], [ 0, -2, 1, 1, 0, 0 ], [ 0, -2, 1, 2, 0, 0 ], [ -1, -2, 1, 3, 0, 0 ] ], 1 ], - [ [ [ -1, -2, 1, 2, 0, 0 ], [ -1, -3, 1, 2, 0, 0 ], [ 0, -2, 1, 2, 0, 0 ], [ -1, -2, 1, 3, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, -2, 1, 2, 0, 0 ], [ -1, -3, 1, 2, 0, 0 ], [ 0, -2, 1, 2, 0, 0 ], [ 0, -3, 1, 2, 0, 0 ] ], 1 ], - [ [ [ -1, -2, 1, 2, 0, 0 ], [ -2, -1, 1, 2, 0, 0 ], [ 0, -2, 1, 2, 0, 0 ], [ 0, -3, 1, 2, 0, 0 ] ], 1 ], - [ [ [ -1, -2, 1, 2, 0, 0 ], [ -2, -1, 1, 2, 0, 0 ], [ 1, -2, 1, 1, 0, 0 ], [ 0, -3, 1, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, -2, 1, 2, 0, 0 ], [ -2, -1, 1, 2, 0, 0 ], [ 1, -2, 1, 1, 0, 0 ], [ -1, -1, 1, 2, 0, 0 ] ], 1 ], - [ [ [ 0, -2, 1, 1, 0, 0 ], [ -2, -1, 1, 2, 0, 0 ], [ 1, -2, 1, 1, 0, 0 ], [ -1, -1, 1, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 0, 1, 2, 0, 0 ], [ -2, -1, 1, 2, 0, 0 ], [ 1, -2, 1, 1, 0, 0 ], [ -1, -1, 1, 2, 0, 0 ] ], 1 ], - [ [ [ -1, 0, 1, 2, 0, 0 ], [ -2, -1, 1, 2, 0, 0 ], [ -2, 0, 1, 2, 0, 0 ], [ -1, -1, 1, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, -1, 1, 2, 0, 0 ], [ -2, -1, 1, 2, 0, 0 ], [ -2, 0, 1, 2, 0, 0 ], [ -1, -1, 1, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, -1, 1, 2, 0, 0 ], [ -2, -1, 1, 2, 0, 0 ], [ -1, -1, 0, 2, 0, 0 ], [ -1, -1, 1, 2, 0, 0 ] ], 1 ], - [ [ [ -3, -1, 1, 2, 0, 0 ], [ -2, -1, 1, 2, 0, 0 ], [ -1, -1, 0, 2, 0, 0 ], [ -2, -1, 2, 2, 0, 0 ] ], 1 ], - [ [ [ -3, -1, 1, 2, 0, 0 ], [ -1, -1, 1, 1, 0, 0 ], [ -1, -1, 0, 2, 0, 0 ], [ -2, -1, 2, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, -1, 1, 2, 0, 0 ], [ -1, -1, 1, 1, 0, 0 ], [ -1, -1, 2, 2, 0, 0 ], [ -2, -1, 2, 2, 0, 0 ] ], 1 ], - [ [ [ -3, -1, 1, 2, 0, 0 ], [ -2, -2, 2, 2, 0, 0 ], [ -1, -1, 2, 2, 0, 0 ], [ -2, -1, 2, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, -1, 1, 2, 0, 0 ], [ -2, -2, 2, 2, 0, 0 ], [ -1, -1, 2, 2, 0, 0 ], [ -1, -2, 1, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, -1, 1, 2, 0, 0 ], [ -2, -2, 2, 2, 0, 0 ], [ -1, -1, 2, 2, 0, 0 ], [ -2, 0, 1, 2, 0, 0 ] ], 1 ], - [ [ [ -3, -1, 1, 2, 0, 0 ], [ -2, -2, 2, 2, 0, 0 ], [ 0, -2, 1, 2, 0, 0 ], [ -2, 0, 1, 2, 0, 0 ] ], 1 ], - [ [ [ -3, -1, 1, 2, 0, 0 ], [ -2, -1, 2, 2, 0, 0 ], [ 0, -2, 1, 2, 0, 0 ], [ -2, 0, 1, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, -1, 1, 2, 0, 0 ], [ -1, -2, 1, 2, 0, 0 ], [ 0, -2, 1, 2, 0, 0 ], [ -2, 0, 1, 2, 0, 0 ] ], 1 ], - [ [ [ -2, -2, 1, 2, 0, 0 ], [ -1, -2, 1, 2, 0, 0 ], [ 0, -2, 1, 2, 0, 0 ], [ -2, 0, 1, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, -1, 1, 2, 0, 0 ], [ -1, -2, 1, 2, 0, 0 ], [ 0, -2, 1, 2, 0, 0 ], [ -2, 0, 1, 2, 0, 0 ] ], 1 ], - [ [ [ -2, -1, 1, 2, 0, 0 ], [ -1, -2, 1, 2, 0, 0 ], [ -1, 0, 1, 2, 0, 0 ], [ -2, 0, 1, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 0, 1, 2, 0, 0 ], [ -1, -2, 1, 2, 0, 0 ], [ -1, 0, 1, 2, 0, 0 ], [ -2, 0, 1, 2, 0, 0 ] ], 1 ], - [ [ [ -3, 0, 1, 2, 0, 0 ], [ -2, -1, 1, 2, 0, 0 ], [ -1, 0, 1, 2, 0, 0 ], [ -2, 0, 1, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 0, 1, 2, 0, 0 ], [ -3, 1, 1, 2, 0, 0 ], [ -1, 0, 1, 2, 0, 0 ], [ -2, 0, 1, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 0, 1, 2, 0, 0 ], [ -3, 1, 1, 2, 0, 0 ], [ -1, 0, 1, 2, 0, 0 ], [ -3, 2, 1, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 0, 1, 2, 0, 0 ], [ -3, 1, 1, 2, 0, 0 ], [ -2, 1, 1, 2, 0, 0 ], [ -3, 2, 1, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 0, 1, 2, 0, 0 ], [ -3, 1, 1, 2, 0, 0 ], [ -2, 0, 1, 2, 0, 0 ], [ -3, 2, 1, 2, 0, 0 ] ], 1 ], - [ [ [ -3, 0, 1, 2, 0, 0 ], [ -3, 1, 1, 2, 0, 0 ], [ -2, 0, 1, 2, 0, 0 ], [ -2, 1, 1, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 1, 1, 2, 0, 0 ], [ -3, 1, 1, 2, 0, 0 ], [ -2, 0, 1, 2, 0, 0 ], [ -2, 1, 1, 2, 0, 0 ] ], 1 ], - [ [ [ -4, 1, 1, 2, 0, 0 ], [ -2, 0, 0, 2, 0, 0 ], [ -2, 0, 1, 2, 0, 0 ], [ -2, 1, 1, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 1, 1, 2, 0, 0 ], [ -2, 0, 0, 2, 0, 0 ], [ -3, 1, 1, 2, 0, 0 ], [ -2, 1, 1, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 1, 1, 2, 0, 0 ], [ -2, 0, 0, 2, 0, 0 ], [ -2, 1, 1, 1, 0, 0 ], [ -2, 1, 1, 2, 0, 0 ] ], 1 ], - [ [ [ -4, 1, 1, 2, 0, 0 ], [ -4, 2, 1, 2, 0, 0 ], [ -2, 1, 1, 1, 0, 0 ], [ -2, 1, 1, 2, 0, 0 ] ], 1 ], - [ [ [ -3, 1, 1, 1, 0, 0 ], [ -4, 2, 1, 2, 0, 0 ], [ -2, 1, 1, 1, 0, 0 ], [ -2, 1, 1, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 1, 1, 1, 0, 0 ], [ -4, 2, 1, 2, 0, 0 ], [ -2, 1, 1, 1, 0, 0 ], [ -1, 1, 1, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 1, 1, 1, 0, 0 ], [ -3, 2, 1, 1, 0, 0 ], [ -2, 1, 1, 1, 0, 0 ], [ -1, 1, 1, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 1, 1, 1, 0, 0 ], [ -3, 2, 1, 1, 0, 0 ], [ -2, 1, 1, 1, 0, 0 ], [ -2, 2, 1, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 1, 1, 1, 0, 0 ], [ -3, 2, 1, 1, 0, 0 ], [ -3, 3, 1, 1, 0, 0 ], [ -2, 2, 1, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 1, 1, 1, 0, 0 ], [ -3, 2, 1, 1, 0, 1 ], [ -3, 3, 1, 1, 0, 0 ], [ -2, 2, 1, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 2, 1, 1, 0, 0 ], [ -3, 2, 1, 1, 0, 1 ], [ -3, 3, 1, 1, 0, 0 ], [ -2, 2, 1, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 1, 1, 0, 0 ], [ -4, 4, 1, 1, 0, 0 ], [ -3, 3, 1, 1, 0, 0 ], [ -2, 2, 1, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 2, 1, 1, 0, 0 ], [ -4, 4, 1, 1, 0, 0 ], [ -3, 3, 1, 1, 0, 0 ], [ -3, 4, 1, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 1, 1, 0, 0 ], [ -4, 4, 1, 1, 0, 0 ], [ -3, 3, 1, 1, 0, 0 ], [ -2, 3, 0, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 2, 1, 1, 0, 0 ], [ -3, 3, 0, 1, 0, 0 ], [ -3, 3, 1, 1, 0, 0 ], [ -2, 3, 0, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 1, 1, 0, 0 ], [ -4, 3, 1, 2, 0, 0 ], [ -3, 3, 1, 1, 0, 0 ], [ -2, 3, 0, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 1, 1, 0, 0 ], [ -4, 3, 1, 2, 0, 0 ], [ -4, 3, 2, 2, 0, 0 ], [ -2, 3, 0, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 1, 1, 0, 0 ], [ -4, 3, 1, 2, 0, 0 ], [ -3, 2, 1, 2, 0, 0 ], [ -2, 3, 0, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 2, 1, 1, 0, 0 ], [ -3, 3, 1, 1, 0, 0 ], [ -3, 2, 1, 2, 0, 0 ], [ -2, 3, 0, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 2, 1, 1, 0, 0 ], [ -3, 3, 1, 1, 0, 0 ], [ -3, 2, 1, 2, 0, 0 ], [ -1, 1, 1, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 3, 1, 2, 0, 0 ], [ -3, 3, 1, 1, 0, 0 ], [ -3, 2, 1, 2, 0, 0 ], [ -1, 1, 1, 1, 0, 0 ] ], 1 ], - [ [ [ -5, 3, 1, 2, 0, 0 ], [ -2, 2, 0, 2, 0, 0 ], [ -3, 2, 1, 2, 0, 0 ], [ -1, 1, 1, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 1, 1, 2, 0, 0 ], [ -2, 2, 0, 2, 0, 0 ], [ -3, 2, 1, 2, 0, 0 ], [ -1, 1, 1, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 1, 1, 2, 0, 0 ], [ -2, 1, 1, 2, 0, 0 ], [ -3, 2, 1, 2, 0, 0 ], [ -1, 1, 1, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 1, 1, 2, 0, 0 ], [ -2, 1, 1, 2, 0, 0 ], [ -2, 1, 1, 1, 0, 0 ], [ -1, 1, 1, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 1, 1, 2, 0, 0 ], [ -3, 2, 1, 2, 0, 0 ], [ -2, 1, 1, 1, 0, 0 ], [ -1, 1, 1, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 1, 1, 2, 0, 0 ], [ -3, 2, 1, 2, 0, 0 ], [ -2, 1, 1, 1, 1, 0 ], [ -1, 1, 1, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 1, 1, 2, 0, 0 ], [ -3, 2, 1, 2, 0, 0 ], [ -2, 1, 1, 1, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -2, 1, 2, 1, 1, 0 ], [ -3, 2, 1, 2, 0, 0 ], [ -2, 1, 1, 1, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -2, 1, 2, 1, 1, 0 ], [ -3, 1, 1, 1, 1, 0 ], [ -2, 1, 1, 1, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 2, 1, 1, 0 ], [ -4, 1, 2, 2, 1, 0 ], [ -2, 1, 1, 1, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 2, 1, 1, 0 ], [ -3, 1, 2, 1, 1, 0 ], [ -2, 1, 1, 1, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -2, 1, 2, 1, 1, 0 ], [ -3, 1, 2, 1, 1, 0 ], [ -2, 1, 1, 1, 1, 0 ], [ -3, 2, 2, 1, 1, 0 ] ], 1 ], - [ [ [ -2, 1, 2, 1, 1, 0 ], [ -3, 1, 2, 1, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ], [ -3, 2, 2, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 2, 1, 1, 0 ], [ -4, 3, 2, 1, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ], [ -3, 2, 2, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 3, 2, 1, 1, 0 ], [ -4, 3, 2, 1, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ], [ -3, 2, 2, 1, 1, 0 ] ], 1 ], - [ [ [ -3, 3, 2, 1, 1, 0 ], [ -4, 2, 2, 1, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ], [ -3, 2, 2, 1, 1, 0 ] ], 1 ], - [ [ [ -3, 3, 2, 1, 1, 0 ], [ -4, 2, 2, 1, 1, 0 ], [ -4, 3, 2, 1, 1, 0 ], [ -3, 2, 2, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 3, 2, 1, 1, 0 ], [ -5, 4, 2, 1, 1, 0 ], [ -4, 3, 2, 1, 1, 0 ], [ -3, 2, 2, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 4, 2, 1, 1, 0 ], [ -5, 4, 2, 1, 1, 0 ], [ -4, 3, 2, 1, 1, 0 ], [ -3, 2, 2, 1, 1, 0 ] ], 1 ], - [ [ [ -4, 4, 2, 1, 1, 0 ], [ -5, 4, 2, 1, 1, 0 ], [ -4, 3, 2, 1, 1, 0 ], [ -3, 3, 2, 1, 1, 0 ] ], 1 ], - [ [ [ -4, 4, 2, 1, 1, 0 ], [ -4, 3, 1, 1, 1, 0 ], [ -4, 3, 2, 1, 1, 0 ], [ -3, 3, 2, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 4, 2, 1, 1, 0 ], [ -4, 3, 1, 1, 1, 0 ], [ -4, 3, 2, 1, 1, 0 ], [ -3, 3, 1, 1, 2, 0 ] ], 1 ], - [ [ [ -3, 3, 1, 1, 1, 0 ], [ -4, 3, 1, 1, 1, 0 ], [ -4, 3, 2, 1, 1, 0 ], [ -3, 3, 1, 1, 2, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 3, 1, 1, 1, 0 ], [ -4, 3, 1, 1, 1, 0 ], [ -4, 3, 2, 1, 1, 0 ], [ -3, 4, 1, 1, 1, 0 ] ], 1 ], - [ [ [ -4, 4, 1, 1, 1, 0 ], [ -4, 3, 1, 1, 1, 0 ], [ -4, 3, 2, 1, 1, 0 ], [ -3, 4, 1, 1, 1, 0 ] ], 1 ], - [ [ [ -4, 4, 1, 1, 1, 0 ], [ -4, 3, 1, 1, 1, 0 ], [ -3, 3, 1, 1, 1, 0 ], [ -3, 4, 1, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 4, 1, 1, 1, 0 ], [ -4, 4, 1, 1, 0, 0 ], [ -3, 3, 1, 1, 1, 0 ], [ -3, 4, 1, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 4, 1, 1, 1, 0 ], [ -4, 4, 1, 1, 0, 0 ], [ -3, 3, 1, 1, 1, 0 ], [ -4, 5, 1, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 4, 1, 1, 1, 0 ], [ -4, 4, 1, 1, 0, 0 ], [ -3, 3, 1, 1, 1, 0 ], [ -3, 4, 1, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 3, 1, 1, 0, 0 ], [ -4, 4, 1, 1, 0, 0 ], [ -3, 3, 1, 1, 1, 0 ], [ -3, 4, 1, 1, 0, 0 ] ], 1 ], - [ [ [ -2, 3, 1, 1, 0, 0 ], [ -3, 3, 1, 1, 0, 0 ], [ -3, 3, 1, 1, 1, 0 ], [ -3, 4, 1, 1, 0, 0 ] ], 1 ], - [ [ [ -2, 3, 1, 1, 0, 0 ], [ -3, 3, 1, 1, 0, 0 ], [ -3, 3, 1, 1, 1, 0 ], [ -2, 3, 1, 1, 1, -1 ] ], 1 ] - ], - [ - [ [ [ -2, 3, 1, 1, 0, 0 ], [ -3, 3, 0, 1, 1, 0 ], [ -3, 3, 1, 1, 1, 0 ], [ -2, 3, 1, 1, 1, -1 ] ], 1 ] - ], - [ - [ [ [ -2, 3, 1, 1, 0, 0 ], [ -2, 3, 1, 1, 0, -1 ], [ -3, 3, 1, 1, 1, 0 ], [ -2, 3, 1, 1, 1, -1 ] ], 1 ], - [ [ [ -2, 3, 1, 1, 0, 0 ], [ -2, 3, 1, 1, 0, -1 ], [ -3, 4, 1, 1, 0, 0 ], [ -2, 3, 1, 1, 1, -1 ] ], 1 ] - ], - [ - [ [ [ -2, 3, 1, 1, 0, 0 ], [ -3, 3, 1, 1, 1, 0 ], [ -3, 4, 1, 1, 0, 0 ], [ -2, 3, 1, 1, 1, -1 ] ], 1 ], - [ [ [ -2, 3, 1, 1, 0, 0 ], [ -3, 3, 1, 1, 1, 0 ], [ -3, 4, 1, 1, 0, 0 ], [ -4, 4, 1, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 3, 1, 1, 0, 0 ], [ -3, 3, 1, 1, 1, 0 ], [ -3, 4, 1, 1, 0, 0 ], [ -3, 3, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 3, 1, 1, 0, 0 ], [ -3, 3, 1, 1, 1, 0 ], [ -3, 4, 0, 1, 1, 0 ], [ -3, 3, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 3, 1, 1, 0, 0 ], [ -3, 4, 1, 1, 1, 0 ], [ -3, 4, 0, 1, 1, 0 ], [ -3, 3, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 3, 1, 1, 1, 0 ], [ -3, 4, 1, 1, 1, 0 ], [ -3, 4, 0, 1, 1, 0 ], [ -3, 3, 0, 1, 1, 0 ] ], 1 ], - [ [ [ -3, 3, 1, 1, 1, 0 ], [ -3, 4, 1, 1, 1, 0 ], [ -4, 4, 1, 1, 1, 0 ], [ -3, 3, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 4, 0, 1, 1, 0 ], [ -3, 4, 1, 1, 1, 0 ], [ -4, 4, 1, 1, 1, 0 ], [ -3, 3, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 4, 0, 1, 1, 0 ], [ -3, 4, 1, 1, 1, 0 ], [ -4, 4, 1, 1, 1, 0 ], [ -4, 4, 0, 1, 1, 0 ] ], 1 ], - [ [ [ -4, 4, 1, 2, 1, 0 ], [ -3, 4, 1, 1, 1, 0 ], [ -4, 4, 1, 1, 1, 0 ], [ -4, 4, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 5, 1, 1, 1, 0 ], [ -3, 4, 1, 1, 1, 0 ], [ -4, 4, 1, 1, 1, 0 ], [ -4, 4, 0, 1, 1, 0 ] ], 1 ], - [ [ [ -4, 5, 1, 1, 1, 0 ], [ -4, 5, 0, 1, 1, 0 ], [ -4, 4, 1, 1, 1, 0 ], [ -4, 4, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 4, 0, 1, 1, 0 ], [ -4, 5, 0, 1, 1, 0 ], [ -4, 4, 1, 1, 1, 0 ], [ -4, 4, 0, 1, 1, 0 ] ], 1 ], - [ [ [ -3, 4, 0, 1, 1, 0 ], [ -4, 5, 0, 1, 1, 0 ], [ -4, 4, 1, 1, 1, 0 ], [ -4, 5, 1, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 4, 0, 1, 1, 0 ], [ -4, 5, 0, 1, 1, 0 ], [ -4, 4, 1, 1, 1, 0 ], [ -3, 4, 1, 1, 1, 0 ] ], 1 ], - [ [ [ -3, 4, 0, 1, 1, 0 ], [ -4, 4, 0, 1, 1, 0 ], [ -4, 4, 1, 1, 1, 0 ], [ -3, 4, 1, 1, 1, 0 ] ], 1 ], - [ [ [ -3, 4, 0, 1, 1, 0 ], [ -4, 4, 0, 1, 1, 0 ], [ -3, 3, 0, 1, 1, 0 ], [ -3, 4, 1, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 4, 0, 1, 1, 0 ], [ -4, 4, 0, 1, 1, 0 ], [ -3, 3, 0, 1, 1, 0 ], [ -4, 5, 0, 1, 1, 0 ] ], 1 ], - [ [ [ -5, 4, 0, 1, 1, 0 ], [ -4, 4, 0, 1, 1, 0 ], [ -3, 3, 0, 1, 1, 0 ], [ -4, 5, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 4, 0, 1, 1, 0 ], [ -4, 4, 0, 1, 1, 0 ], [ -3, 3, 0, 1, 1, 0 ], [ -3, 4, 0, 1, 1, 0 ] ], 1 ], - [ [ [ -4, 3, 0, 1, 1, 0 ], [ -4, 4, 0, 1, 1, 0 ], [ -3, 3, 0, 1, 1, 0 ], [ -3, 4, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 3, 0, 1, 1, 0 ], [ -4, 4, 0, 1, 1, 0 ], [ -4, 5, 0, 1, 1, 0 ], [ -3, 4, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 3, 0, 1, 1, 0 ], [ -3, 3, -1, 1, 1, 0 ], [ -4, 5, 0, 1, 1, 0 ], [ -3, 4, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -6, 5, 0, 1, 1, 0 ], [ -3, 3, -1, 1, 1, 0 ], [ -4, 5, 0, 1, 1, 0 ], [ -3, 4, 0, 1, 1, 0 ] ], 1 ], - [ [ [ -6, 5, 0, 1, 1, 0 ], [ -3, 3, -1, 1, 1, 0 ], [ -4, 5, 0, 1, 1, 0 ], [ -4, 6, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -6, 5, 0, 1, 1, 0 ], [ -3, 3, -1, 1, 1, 0 ], [ -5, 6, -1, 1, 1, 0 ], [ -4, 6, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -6, 6, -1, 1, 1, 0 ], [ -3, 3, -1, 1, 1, 0 ], [ -5, 6, -1, 1, 1, 0 ], [ -4, 6, 0, 1, 1, 0 ] ], 1 ], - [ [ [ -6, 6, -1, 1, 1, 0 ], [ -3, 3, -1, 1, 1, 0 ], [ -5, 6, 0, 1, 1, 0 ], [ -4, 6, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -6, 6, -1, 1, 1, 0 ], [ -5, 6, -1, 1, 1, 0 ], [ -5, 6, 0, 1, 1, 0 ], [ -4, 6, 0, 1, 1, 0 ] ], 1 ], - [ [ [ -6, 6, 0, 1, 1, 0 ], [ -5, 6, -1, 1, 1, 0 ], [ -5, 6, 0, 1, 1, 0 ], [ -4, 6, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -6, 6, 0, 1, 1, 0 ], [ -5, 6, -1, 1, 1, 0 ], [ -5, 6, 0, 1, 1, 0 ], [ -4, 5, 0, 1, 1, 0 ] ], 1 ], - [ [ [ -6, 6, 0, 1, 1, 0 ], [ -5, 6, -1, 1, 1, 0 ], [ -4, 6, -1, 1, 1, 0 ], [ -4, 5, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 5, -1, 1, 1, 0 ], [ -5, 6, -1, 1, 1, 0 ], [ -4, 6, -1, 1, 1, 0 ], [ -4, 5, 0, 1, 1, 0 ] ], 1 ], - [ [ [ -5, 5, -1, 1, 1, 0 ], [ -4, 5, -1, 1, 1, 0 ], [ -4, 6, -1, 1, 1, 0 ], [ -4, 5, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 5, -1, 1, 1, 0 ], [ -4, 5, -1, 1, 1, 0 ], [ -3, 5, -2, 1, 1, 0 ], [ -4, 5, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 5, -1, 1, 1, 0 ], [ -4, 5, -1, 1, 1, 0 ], [ -3, 5, -2, 1, 1, 0 ], [ -3, 5, -1, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 5, -2, 1, 1, 0 ], [ -4, 5, -1, 1, 1, 0 ], [ -3, 5, -2, 1, 1, 0 ], [ -3, 5, -1, 1, 1, 0 ] ], 1 ], - [ [ [ -4, 5, -2, 1, 1, 0 ], [ -4, 5, -1, 1, 1, 0 ], [ -3, 5, -2, 1, 1, 0 ], [ -4, 6, -1, 1, 1, 0 ] ], 1 ], - [ [ [ -4, 5, -2, 1, 1, 0 ], [ -4, 5, -1, 1, 1, 0 ], [ -4, 5, -1, 2, 1, 0 ], [ -4, 6, -1, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 5, -2, 1, 1, 0 ], [ -4, 5, -1, 1, 1, 0 ], [ -4, 5, -1, 2, 1, 0 ], [ -3, 5, -2, 1, 1, 0 ] ], 1 ], - [ [ [ -4, 5, -2, 1, 1, 0 ], [ -4, 5, -1, 1, 1, 0 ], [ -3, 5, -1, 1, 1, 0 ], [ -3, 5, -2, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 5, -2, 1, 1, 0 ], [ -4, 5, -1, 1, 1, 0 ], [ -2, 4, -2, 1, 1, 0 ], [ -3, 5, -2, 1, 1, 0 ] ], 1 ], - [ [ [ -4, 5, -2, 1, 1, 0 ], [ -4, 5, -1, 1, 1, 0 ], [ -2, 4, -2, 1, 1, 0 ], [ -3, 4, -2, 1, 1, 0 ] ], 1 ], - [ [ [ -4, 5, -2, 1, 1, 0 ], [ -3, 5, -2, 1, 1, 0 ], [ -2, 4, -2, 1, 1, 0 ], [ -3, 4, -2, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 5, -2, 1, 1, 0 ], [ -2, 5, -2, 0, 1, 0 ], [ -2, 4, -2, 1, 1, 0 ], [ -3, 4, -2, 1, 1, 0 ] ], 1 ], - [ [ [ -4, 5, -2, 1, 1, 0 ], [ -2, 5, -2, 0, 1, 0 ], [ -2, 4, -2, 1, 1, 0 ], [ -4, 6, -2, 1, 1, 0 ] ], 1 ], - [ [ [ -4, 5, -2, 1, 1, 0 ], [ -2, 5, -2, 0, 1, 0 ], [ -3, 5, -2, 1, 1, 0 ], [ -4, 6, -2, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 5, -2, 1, 1, 0 ], [ -2, 5, -2, 0, 1, 0 ], [ -3, 5, -2, 1, 1, 0 ], [ -4, 6, -2, 1, 1, 0 ] ], 1 ], - [ [ [ -5, 5, -2, 1, 1, 0 ], [ -4, 5, -2, 1, 1, 0 ], [ -3, 5, -2, 1, 1, 0 ], [ -4, 6, -2, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 5, -2, 1, 1, 0 ], [ -4, 5, -2, 1, 1, 0 ], [ -4, 7, -2, 1, 1, 0 ], [ -4, 6, -2, 1, 1, 0 ] ], 1 ], - [ [ [ -5, 5, -2, 1, 1, 0 ], [ -5, 6, -2, 1, 1, 0 ], [ -4, 7, -2, 1, 1, 0 ], [ -4, 6, -2, 1, 1, 0 ] ], 1 ], - [ [ [ -6, 6, -2, 1, 1, 0 ], [ -5, 6, -2, 1, 1, 0 ], [ -4, 7, -2, 1, 1, 0 ], [ -4, 6, -2, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -6, 7, -2, 1, 1, 0 ], [ -5, 6, -2, 1, 1, 0 ], [ -4, 7, -2, 1, 1, 0 ], [ -4, 6, -2, 1, 1, 0 ] ], 1 ], - [ [ [ -6, 7, -2, 1, 1, 0 ], [ -5, 6, -2, 1, 1, 0 ], [ -5, 7, -2, 1, 1, 0 ], [ -4, 6, -2, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -6, 7, -2, 1, 1, 0 ], [ -5, 6, -2, 1, 1, 0 ], [ -5, 7, -2, 1, 1, 0 ], [ -4, 7, -2, 1, 1, 0 ] ], 1 ], - [ [ [ -6, 7, -2, 1, 1, 0 ], [ "Rest" ], [ -5, 7, -2, 1, 1, 0 ], [ -4, 7, -2, 1, 1, 0 ] ], 1 ], - [ [ [ -6, 7, -2, 1, 1, 0 ], [ "Rest" ], [ -5, 7, -2, 1, 1, 0 ], [ "Rest" ] ], 1 ], - [ [ [ -6, 7, -2, 1, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1 ] - ] - ] -], -"last_changes": -[ - [ [ -5, 5, -2, 1, 1, 0 ], [ -5, 6, -2, 1, 1, 0 ], [ -4, 7, -2, 1, 1, 0 ], [ -4, 6, -2, 1, 1, 0 ] ], - [ [ -6, 6, -2, 1, 1, 0 ], [ -5, 6, -2, 1, 1, 0 ], [ -4, 7, -2, 1, 1, 0 ], [ -4, 6, -2, 1, 1, 0 ] ], - [ [ -6, 7, -2, 1, 1, 0 ], [ -5, 6, -2, 1, 1, 0 ], [ -4, 7, -2, 1, 1, 0 ], [ -4, 6, -2, 1, 1, 0 ] ], - [ [ -6, 7, -2, 1, 1, 0 ], [ -5, 6, -2, 1, 1, 0 ], [ -5, 7, -2, 1, 1, 0 ], [ -4, 6, -2, 1, 1, 0 ] ], - [ [ -6, 7, -2, 1, 1, 0 ], [ -5, 6, -2, 1, 1, 0 ], [ -5, 7, -2, 1, 1, 0 ], [ -4, 7, -2, 1, 1, 0 ] ] -], -"cur_uid": "7e230015", -"ref_uid": "nil", -"order_seed": 389930, -"dur_seed": 736878, -"motifs_seed": 479673, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ -1200, 1200, 0.0020576131687243, 0.068181818181818, 0.074074074074074, 0.0625, 0.20576131687243, 0.0625, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.78600823045268, 0.068181818181818, 0.98971193415638, 0.0625 ], -"passages_weights": [ 1, 1, 0.48, 1, 1 ], -"hd_exp": 10, -"hd_invert": 0, -"order": -[ - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 1, 3 ], [ 2, 0 ], [ ] ], - [ [ 0, 3 ], [ 2, 1 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 3, 1 ], [ 2, 0 ], [ ] ], - [ [ 2 ], [ 1, 3, 0 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 0, 3 ], [ 1, 2 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 2 ], [ 0, 3, 1 ], [ ] ], - [ [ 3, 2 ], [ 0, 1 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 2 ], [ 3, 0, 1 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 2, 0 ], [ 3, 1 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 2 ], [ 0, 3, 1 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 1, 3 ], [ 0, 2 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0, 3 ], [ 2, 1 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 2, 3 ], [ 1, 0 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 3, 2 ], [ 0, 1 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 1, 0 ], [ 2, 3 ], [ ] ], - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ], - [ [ 2, 0 ], [ 3, 1 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ], - [ [ 0, 2 ], [ 1, 3 ], [ ] ], - [ [ 0, 2 ], [ 3, 1 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 3, 2 ], [ 0, 1 ], [ ] ], - [ [ 3 ], [ 0, 1, 2 ], [ ] ], - [ [ 3, 0 ], [ 1, 2 ], [ ] ], - [ [ 2 ], [ 3, 0, 1 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 2, 0, 3 ], [ 1 ], [ ] ], - [ [ 3 ], [ 0, 1, 2 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 2 ], [ 0, 3, 1 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 2 ], [ 0, 1, 3 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 0, 3 ], [ 1, 2 ], [ ] ], - [ [ 2, 0 ], [ 1, 3 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 1, 3 ], [ 0, 2 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 1, 2 ], [ 0, 3 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 2, 1 ], [ 0, 3 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 3, 2 ], [ 1, 0 ], [ ] ], - [ [ 0, 1 ], [ 3, 2 ], [ ] ], - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 1 ], [ 0, 3, 2 ], [ ] ], - [ [ 0, 1 ], [ 3, 2 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 100, 100 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3/tmp/tmp_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3/tmp/tmp_mus_model.json deleted file mode 100644 index 487fc67..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3/tmp/tmp_mus_model.json +++ /dev/null @@ -1,532 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1 ], - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 2.375 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.625 ] - ], - [ - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 3.5 ] - ], - [ - [ [ [ 0, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 2.5 ] - ], - [ - [ [ [ 0, 0, 0, -1, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.375 ] - ], - [ - [ [ [ 0, 0, 0, -1, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 1, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 1, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, -1, 1, 0, 0, 0 ], [ 0, 0, 1, -1, 0, 0 ] ], 1.875 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 1, -1, 0, 0 ], [ 0, 0, 1, -1, 0, 0 ] ], 1 ], - [ [ [ 1, -1, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 1, -1, 0, 0 ], [ 0, 0, 1, -1, 0, 0 ] ], 3.375 ] - ], - [ - [ [ [ 1, -1, 1, 0, 0, 0 ], [ 2, -1, 1, -1, 0, 0 ], [ 1, 0, 1, -1, 0, 0 ], [ 0, 0, 1, -1, 0, 0 ] ], 1 ], - [ [ [ 1, -1, 1, 0, 0, 0 ], [ 2, -1, 1, -1, 0, 0 ], [ 1, 0, 1, -1, 0, 0 ], [ 1, -1, 1, -1, 0, 0 ] ], 1 ], - [ [ [ 2, 0, 1, -1, 0, 0 ], [ 2, -1, 1, -1, 0, 0 ], [ 1, 0, 1, -1, 0, 0 ], [ 1, -1, 1, -1, 0, 0 ] ], 1.5 ] - ], - [ - [ [ [ 2, 0, 1, -1, 0, 0 ], [ 2, -1, 1, -1, 0, 0 ], [ 1, 0, 1, -1, 0, 0 ], [ 2, -1, 1, -2, 0, 0 ] ], 1 ], - [ [ [ 3, 0, 1, -2, 0, 0 ], [ 2, -1, 1, -1, 0, 0 ], [ 1, 0, 1, -1, 0, 0 ], [ 2, -1, 1, -2, 0, 0 ] ], 1.75 ] - ], - [ - [ [ [ 3, 0, 1, -2, 0, 0 ], [ 1, 1, 1, -2, 0, 0 ], [ 1, 0, 1, -1, 0, 0 ], [ 2, -1, 1, -2, 0, 0 ] ], 1 ], - [ [ [ 3, 0, 1, -2, 0, 0 ], [ 1, 1, 1, -2, 0, 0 ], [ 1, 0, 1, -2, 0, 0 ], [ 2, -1, 1, -2, 0, 0 ] ], 3.625 ] - ], - [ - [ [ [ 3, 0, 1, -2, 0, 0 ], [ 1, 1, 1, -2, 0, 0 ], [ 1, 0, 1, -2, 0, 0 ], [ 0, 1, 1, -2, 0, 0 ] ], 1.5 ] - ], - [ - [ [ [ 3, 0, 1, -2, 0, 0 ], [ 1, 1, 1, -2, 0, 0 ], [ 0, 2, 1, -2, 0, 0 ], [ 0, 1, 1, -2, 0, 0 ] ], 3 ] - ], - [ - [ [ [ 2, 1, 1, -2, 0, 0 ], [ 1, 1, 1, -2, 0, 0 ], [ 0, 2, 1, -2, 0, 0 ], [ 0, 1, 1, -2, 0, 0 ] ], 1 ], - [ [ [ 2, 1, 1, -2, 0, 0 ], [ 1, 1, 1, -2, 0, 0 ], [ 0, 2, 1, -2, 0, 0 ], [ -1, 3, 1, -2, 0, 0 ] ], 1 ], - [ [ [ 2, 1, 1, -2, 0, 0 ], [ 1, 2, 1, -2, 0, 0 ], [ 0, 2, 1, -2, 0, 0 ], [ -1, 3, 1, -2, 0, 0 ] ], 1.75 ] - ], - [ - [ [ [ 1, 3, 1, -2, 0, 0 ], [ 1, 2, 1, -2, 0, 0 ], [ 0, 2, 1, -2, 0, 0 ], [ -1, 3, 1, -2, 0, 0 ] ], 1 ], - [ [ [ 1, 3, 1, -2, 0, 0 ], [ 0, 3, 1, -2, 0, 0 ], [ 0, 2, 1, -2, 0, 0 ], [ -1, 3, 1, -2, 0, 0 ] ], 2.5 ] - ], - [ - [ [ [ 1, 3, 1, -2, 0, 0 ], [ 0, 3, 1, -2, 0, 0 ], [ 0, 2, 1, -2, 0, 0 ], [ 0, 2, 0, -2, 0, 0 ] ], 1.75 ] - ], - [ - [ [ [ 1, 3, 1, -2, 0, 0 ], [ 0, 3, 1, -2, 0, 0 ], [ 0, 2, 1, -2, 0, 0 ], [ 0, 1, 1, -2, 0, 0 ] ], 1.125 ] - ], - [ - [ [ [ 1, 3, 1, -2, 0, 0 ], [ 0, 3, 1, -2, 0, 0 ], [ -1, 1, 1, -1, 0, 0 ], [ 0, 1, 1, -2, 0, 0 ] ], 1 ], - [ [ [ 1, 3, 1, -2, 0, 0 ], [ 0, 2, 1, -2, 0, 0 ], [ -1, 1, 1, -1, 0, 0 ], [ 0, 1, 1, -2, 0, 0 ] ], 1 ], - [ [ [ 1, 2, 1, -2, 0, 0 ], [ 0, 2, 1, -2, 0, 0 ], [ -1, 1, 1, -1, 0, 0 ], [ 0, 1, 1, -2, 0, 0 ] ], 1.125 ] - ], - [ - [ [ [ 1, 1, 1, -2, 0, 1 ], [ 0, 2, 1, -2, 0, 0 ], [ -1, 1, 1, -1, 0, 0 ], [ 0, 1, 1, -2, 0, 0 ] ], 3.25 ] - ], - [ - [ [ [ 1, 1, 1, -2, 0, 1 ], [ 0, 1, 1, -2, 0, 1 ], [ -1, 1, 1, -1, 0, 0 ], [ 0, 1, 1, -2, 0, 0 ] ], 1.875 ] - ], - [ - [ [ [ 1, 1, 1, -2, 0, 1 ], [ 0, 1, 1, -2, 0, 1 ], [ -1, 1, 1, -1, 0, 0 ], [ -1, 1, 1, -1, 0, 1 ] ], 1 ], - [ [ [ 1, 1, 1, -1, 0, 0 ], [ 0, 1, 1, -2, 0, 1 ], [ -1, 1, 1, -1, 0, 0 ], [ -1, 1, 1, -1, 0, 1 ] ], 1 ], - [ [ [ 1, 1, 1, -1, 0, 0 ], [ 0, 1, 1, -1, 0, 0 ], [ -1, 1, 1, -1, 0, 0 ], [ -1, 1, 1, -1, 0, 1 ] ], 2.25 ] - ], - [ - [ [ [ 1, 1, 1, -1, 0, 0 ], [ 0, 1, 1, -1, 0, 0 ], [ -1, 1, 1, -1, 0, 0 ], [ 1, 0, 1, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 2, 1, -1, 0, 0 ], [ 0, 1, 1, -1, 0, 0 ], [ -1, 1, 1, -1, 0, 0 ], [ 1, 0, 1, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 2, 1, -1, 0, 0 ], [ 0, 1, 1, -1, 0, 0 ], [ -1, 2, 1, -1, 0, 0 ], [ 1, 0, 1, -1, 0, 0 ] ], 2.625 ] - ], - [ - [ [ [ 0, 2, 1, -1, 0, 0 ], [ 0, 1, 1, -1, 0, 0 ], [ -1, 2, 1, -1, 0, 0 ], [ -1, 3, 1, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 2, 1, -1, 0, 0 ], [ -2, 3, 1, -1, 0, 0 ], [ -1, 2, 1, -1, 0, 0 ], [ -1, 3, 1, -1, 0, 0 ] ], 2.75 ] - ], - [ - [ [ [ 0, 2, 1, -1, 0, 0 ], [ -2, 3, 1, -1, 0, 0 ], [ -2, 4, 1, -1, 0, 0 ], [ -1, 3, 1, -1, 0, 0 ] ], 3.5 ] - ], - [ - [ [ [ 0, 2, 1, -1, 0, 0 ], [ -2, 3, 1, -1, 0, 0 ], [ -2, 4, 1, -1, 0, 0 ], [ -1, 3, 0, -1, 0, 0 ] ], 1 ], - [ [ [ -1, 3, 1, -1, 0, 0 ], [ -2, 3, 1, -1, 0, 0 ], [ -2, 4, 1, -1, 0, 0 ], [ -1, 3, 0, -1, 0, 0 ] ], 1 ], - [ [ [ -1, 3, 1, -1, 0, 0 ], [ -2, 3, 1, -1, 0, 0 ], [ -3, 3, 1, 0, 0, 0 ], [ -1, 3, 0, -1, 0, 0 ] ], 1.875 ] - ], - [ - [ [ [ -1, 3, 1, -1, 0, 0 ], [ -2, 3, 1, -1, 0, 0 ], [ -3, 3, 1, 0, 0, 0 ], [ -2, 3, 1, 0, 0, 0 ] ], 2.75 ] - ], - [ - [ [ [ -1, 3, 1, -1, 0, 0 ], [ -2, 3, 1, -1, 0, 0 ], [ -3, 3, 1, 0, 0, 0 ], [ -2, 3, 2, -1, 0, 0 ] ], 2.375 ] - ], - [ - [ [ [ -2, 3, 2, 0, 0, 0 ], [ -2, 3, 1, -1, 0, 0 ], [ -3, 3, 1, 0, 0, 0 ], [ -2, 3, 2, -1, 0, 0 ] ], 1 ], - [ [ [ -2, 3, 2, 0, 0, 0 ], [ -2, 3, 1, -1, 0, 0 ], [ -3, 3, 1, 0, 0, 0 ], [ -2, 3, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 3, 2, 0, 0, 0 ], [ -3, 3, 2, 0, 0, 0 ], [ -3, 3, 1, 0, 0, 0 ], [ -2, 3, 0, 0, 0, 0 ] ], 3.25 ] - ], - [ - [ [ [ -2, 3, 2, 0, 0, 0 ], [ -3, 3, 2, 0, 0, 0 ], [ -3, 3, 1, 0, 0, 0 ], [ -2, 3, 2, 0, -1, 0 ] ], 1 ], - [ [ [ -2, 3, 2, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ], [ -3, 3, 1, 0, 0, 0 ], [ -2, 3, 2, 0, -1, 0 ] ], 1 ], - [ [ [ -2, 3, 2, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ], [ -4, 3, 2, 1, 0, 0 ], [ -2, 3, 2, 0, -1, 0 ] ], 1.125 ] - ], - [ - [ [ [ -2, 3, 2, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ], [ -4, 3, 2, 1, 0, 0 ], [ -3, 2, 2, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 4, 1, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ], [ -4, 3, 2, 1, 0, 0 ], [ -3, 2, 2, 1, 0, 0 ] ], 1.25 ] - ], - [ - [ [ [ -3, 3, 2, 1, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ], [ -4, 3, 2, 1, 0, 0 ], [ -3, 2, 2, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 3, 2, 1, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ], [ -3, 3, 2, 0, 0, 0 ], [ -3, 2, 2, 1, 0, 0 ] ], 2.375 ] - ], - [ - [ [ [ -3, 4, 3, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ], [ -3, 3, 2, 0, 0, 0 ], [ -3, 2, 2, 1, 0, 0 ] ], 3 ] - ], - [ - [ [ [ -3, 4, 3, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ], [ -3, 4, 3, -1, 0, 0 ], [ -3, 2, 2, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 4, 3, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ], [ -3, 4, 3, -1, 0, 0 ], [ -3, 3, 3, 0, 0, 0 ] ], 1 ], - [ [ [ -3, 4, 3, 0, 0, 0 ], [ -2, 3, 3, 0, 0, 0 ], [ -3, 4, 3, -1, 0, 0 ], [ -3, 3, 3, 0, 0, 0 ] ], 2.75 ] - ], - [ - [ [ [ -3, 4, 3, 0, 0, 0 ], [ -2, 3, 3, 0, 0, 0 ], [ -4, 4, 3, 0, 0, 0 ], [ -3, 3, 3, 0, 0, 0 ] ], 1 ], - [ [ [ -3, 4, 3, 0, 0, 0 ], [ -3, 5, 3, 0, 0, 0 ], [ -4, 4, 3, 0, 0, 0 ], [ -3, 3, 3, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 4, 3, 0, 0, 0 ], [ -3, 5, 3, 0, 0, 0 ], [ -4, 4, 3, 0, 0, 0 ], [ -4, 5, 3, 0, 0, 0 ] ], 3.5 ] - ], - [ - [ [ [ -3, 4, 3, 0, 0, 0 ], [ -3, 5, 3, 0, 0, 0 ], [ -4, 4, 3, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ] ], 1 ], - [ [ [ -3, 4, 3, 0, 0, 0 ], [ -3, 5, 3, 0, 0, 0 ], [ -3, 3, 3, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ] ], 1 ], - [ [ [ -3, 4, 3, 0, 0, 0 ], [ -2, 4, 2, 0, 0, 0 ], [ -3, 3, 3, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ] ], 1.875 ] - ], - [ - [ [ [ -3, 4, 3, 0, 0, 0 ], [ -2, 3, 3, 0, 0, 0 ], [ -3, 3, 3, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 3, 2, 0, 0, 0 ], [ -2, 3, 3, 0, 0, 0 ], [ -3, 3, 3, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ] ], 2.5 ] - ], - [ - [ [ [ -2, 4, 3, 0, 0, 0 ], [ -2, 3, 3, 0, 0, 0 ], [ -3, 3, 3, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 4, 3, 0, 0, 0 ], [ -2, 3, 3, 0, 0, 0 ], [ -3, 4, 3, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ] ], 3.25 ] - ], - [ - [ [ [ -1, 3, 2, 0, 0, 0 ], [ -2, 3, 3, 0, 0, 0 ], [ -3, 4, 3, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 3, 2, 0, 0, 0 ], [ -3, 5, 3, 0, 0, 0 ], [ -3, 4, 3, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ] ], 2.625 ] - ], - [ - [ [ [ -1, 3, 2, 0, 0, 0 ], [ -2, 4, 2, 0, 0, 0 ], [ -3, 4, 3, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ] ], 1.125 ] - ], - [ - [ [ [ -1, 3, 2, 0, 0, 0 ], [ -2, 4, 2, 0, 0, 0 ], [ -3, 4, 3, 0, 0, 0 ], [ -3, 3, 2, 0, 0, 0 ] ], 1.625 ] - ], - [ - [ [ [ -1, 3, 2, 0, 0, 0 ], [ -2, 4, 2, 0, 0, 0 ], [ -2, 3, 2, 0, 0, 0 ], [ -3, 3, 2, 0, 0, 0 ] ], 2.75 ] - ], - [ - [ [ [ -1, 3, 2, 0, 0, 0 ], [ -2, 4, 2, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ], [ -3, 3, 2, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 3, 2, 0, 0, 0 ], [ -2, 4, 2, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ], [ -4, 5, 2, 0, 0, 0 ] ], 2 ] - ], - [ - [ [ [ -2, 5, 2, 0, 0, 0 ], [ -2, 4, 2, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ], [ -4, 5, 2, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 5, 2, 0, 0, 0 ], [ -3, 5, 2, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ], [ -4, 5, 2, 0, 0, 0 ] ], 3.25 ] - ], - [ - [ [ [ -2, 5, 2, 0, 0, 0 ], [ -3, 5, 2, 0, 0, 0 ], [ -4, 6, 2, 0, 0, 0 ], [ -4, 5, 2, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 5, 2, 0, 0, 0 ], [ -3, 5, 2, 0, 0, 0 ], [ -3, 5, 1, 0, 0, 0 ], [ -4, 5, 2, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 5, 2, 0, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ], [ -3, 5, 1, 0, 0, 0 ], [ -4, 5, 2, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 5, 2, -1, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ], [ -3, 5, 1, 0, 0, 0 ], [ -4, 5, 2, 0, 0, 0 ] ], 1.375 ] - ], - [ - [ [ [ -1, 5, 2, -1, 0, 0 ], [ -3, 4, 2, 0, 0, 0 ], [ -3, 5, 1, 0, 0, 0 ], [ -3, 5, 2, -1, 0, 0 ] ], 1 ], - [ [ [ -1, 5, 2, -1, 0, 0 ], [ -3, 5, 1, -1, 0, 0 ], [ -3, 5, 1, 0, 0, 0 ], [ -3, 5, 2, -1, 0, 0 ] ], 1.875 ] - ], - [ - [ [ [ -1, 5, 2, -1, 0, 0 ], [ -3, 5, 1, -1, 0, 0 ], [ -3, 5, 1, 0, 0, 0 ], [ -2, 4, 1, -1, 0, 0 ] ], 2.875 ] - ], - [ - [ [ [ -1, 5, 2, -1, 0, 0 ], [ -3, 5, 1, -1, 0, 0 ], [ -2, 5, 1, -1, 0, 0 ], [ -2, 4, 1, -1, 0, 0 ] ], 1 ], - [ [ [ -1, 5, 2, -1, 0, 0 ], [ -2, 4, 2, -1, 0, 0 ], [ -2, 5, 1, -1, 0, 0 ], [ -2, 4, 1, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 3, 1, -1, 0, 0 ], [ -2, 4, 2, -1, 0, 0 ], [ -2, 5, 1, -1, 0, 0 ], [ -2, 4, 1, -1, 0, 0 ] ], 3.25 ] - ], - [ - [ [ [ 0, 3, 1, -1, 0, 0 ], [ -1, 3, 1, -1, 0, 0 ], [ -2, 5, 1, -1, 0, 0 ], [ -2, 4, 1, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 3, 1, -1, 0, 0 ], [ -1, 3, 1, -1, 0, 0 ], [ -2, 5, 1, -1, 0, 0 ], [ -2, 3, 1, -1, 0, 0 ] ], 1.625 ] - ], - [ - [ [ [ 0, 3, 1, -1, 0, 0 ], [ -1, 3, 1, -1, 0, 0 ], [ -2, 5, 1, -1, 0, 0 ], [ -3, 5, 1, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 3, 1, -1, 0, 0 ], [ -2, 4, 1, -1, 0, 0 ], [ -2, 5, 1, -1, 0, 0 ], [ -3, 5, 1, -1, 0, 0 ] ], 2.375 ] - ], - [ - [ [ [ 0, 3, 1, -1, 0, 0 ], [ -3, 6, 1, -1, 0, 0 ], [ -2, 5, 1, -1, 0, 0 ], [ -3, 5, 1, -1, 0, 0 ] ], 2.375 ] - ], - [ - [ [ [ 0, 3, 1, -1, 0, 0 ], [ -3, 6, 1, -1, 0, 0 ], [ -2, 4, 1, -1, 0, 0 ], [ -3, 5, 1, -1, 0, 0 ] ], 3.125 ] - ], - [ - [ [ [ 0, 3, 1, -1, 0, 0 ], [ -3, 6, 1, -1, 0, 0 ], [ -1, 3, 0, -1, 0, 0 ], [ -3, 5, 1, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 3, 1, -1, 0, 0 ], [ -1, 4, 1, -1, 0, 0 ], [ -1, 3, 0, -1, 0, 0 ], [ -3, 5, 1, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 3, 1, -1, 0, 0 ], [ -1, 4, 1, -1, 0, 0 ], [ -1, 3, 0, -1, 0, 0 ], [ -1, 3, 1, -1, 0, 0 ] ], 3.25 ] - ], - [ - [ [ [ 1, 2, 1, -1, 0, 0 ], [ -1, 4, 1, -1, 0, 0 ], [ -1, 3, 0, -1, 0, 0 ], [ -1, 3, 1, -1, 0, 0 ] ], 1 ], - [ [ [ 1, 2, 1, -1, 0, 0 ], [ 0, 3, 0, -1, 0, 0 ], [ -1, 3, 0, -1, 0, 0 ], [ -1, 3, 1, -1, 0, 0 ] ], 1.75 ] - ], - [ - [ [ [ 0, 4, 1, -1, 0, 0 ], [ 0, 3, 0, -1, 0, 0 ], [ -1, 3, 0, -1, 0, 0 ], [ -1, 3, 1, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 4, 1, -1, 0, 0 ], [ 0, 2, 1, -1, 0, 0 ], [ -1, 3, 0, -1, 0, 0 ], [ -1, 3, 1, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 4, 1, -1, 0, 0 ], [ 0, 2, 1, -1, 0, 0 ], [ -1, 2, 1, -1, 0, 0 ], [ -1, 3, 1, -1, 0, 0 ] ], 1.75 ] - ], - [ - [ [ [ 0, 4, 1, -1, 0, 0 ], [ -2, 4, 1, -1, 0, 0 ], [ -1, 2, 1, -1, 0, 0 ], [ -1, 3, 1, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 4, 1, -1, 0, 0 ], [ -2, 4, 1, -1, 0, 0 ], [ -2, 3, 1, -1, 0, 0 ], [ -1, 3, 1, -1, 0, 0 ] ], 2.375 ] - ], - [ - [ [ [ 0, 4, 1, -1, 0, 0 ], [ -2, 4, 1, -1, 0, 0 ], [ -2, 3, 1, -1, 0, 0 ], [ 0, 3, 1, -2, 0, 0 ] ], 1 ], - [ [ [ 0, 3, 1, -1, 0, 0 ], [ -2, 4, 1, -1, 0, 0 ], [ -2, 3, 1, -1, 0, 0 ], [ 0, 3, 1, -2, 0, 0 ] ], 1 ], - [ [ [ 0, 3, 1, -1, 0, 0 ], [ -1, 3, 1, -1, 0, 0 ], [ -2, 3, 1, -1, 0, 0 ], [ 0, 3, 1, -2, 0, 0 ] ], 3.25 ] - ], - [ - [ [ [ 0, 3, 1, -1, 0, 0 ], [ -1, 3, 1, -2, 0, 0 ], [ -2, 3, 1, -1, 0, 0 ], [ 0, 3, 1, -2, 0, 0 ] ], 1.375 ] - ], - [ - [ [ [ 0, 3, 1, -1, 0, 0 ], [ -1, 3, 1, -1, 0, -1 ], [ -2, 3, 1, -1, 0, 0 ], [ 0, 3, 1, -2, 0, 0 ] ], 1 ], - [ [ [ 0, 3, 1, -1, 0, 0 ], [ -1, 3, 1, -1, 0, -1 ], [ -2, 3, 1, -1, 0, 0 ], [ 0, 3, 1, -1, 0, -1 ] ], 1 ], - [ [ [ 0, 3, 1, -1, 0, 0 ], [ -1, 3, 1, -1, 0, -1 ], [ -2, 4, 1, -1, 0, 0 ], [ 0, 3, 1, -1, 0, -1 ] ], 1.25 ] - ], - [ - [ [ [ 0, 3, 1, -1, 0, 0 ], [ -1, 2, 1, -1, 0, 0 ], [ -2, 4, 1, -1, 0, 0 ], [ 0, 3, 1, -1, 0, -1 ] ], 2.75 ] - ], - [ - [ [ [ -1, 3, 1, 0, 0, -1 ], [ -1, 2, 1, -1, 0, 0 ], [ -2, 4, 1, -1, 0, 0 ], [ 0, 3, 1, -1, 0, -1 ] ], 1 ], - [ [ [ -1, 3, 1, 0, 0, -1 ], [ -1, 3, 1, -1, 0, 0 ], [ -2, 4, 1, -1, 0, 0 ], [ 0, 3, 1, -1, 0, -1 ] ], 1 ], - [ [ [ -1, 3, 1, 0, 0, -1 ], [ -1, 3, 1, -1, 0, 0 ], [ -1, 3, 1, -1, 0, -1 ], [ 0, 3, 1, -1, 0, -1 ] ], 1.5 ] - ], - [ - [ [ [ -1, 3, 1, 0, 0, -1 ], [ -2, 3, 1, 0, 0, -1 ], [ -1, 3, 1, -1, 0, -1 ], [ 0, 3, 1, -1, 0, -1 ] ], 1.625 ] - ], - [ - [ [ [ 0, 4, 1, -1, 0, -1 ], [ -2, 3, 1, 0, 0, -1 ], [ -1, 3, 1, -1, 0, -1 ], [ 0, 3, 1, -1, 0, -1 ] ], 1 ], - [ [ [ 0, 4, 1, -1, 0, -1 ], [ -2, 3, 1, 0, 0, -1 ], [ -1, 3, 1, -1, 0, -1 ], [ -1, 4, 1, -1, 0, -1 ] ], 1 ], - [ [ [ 0, 4, 1, -1, 0, -1 ], [ -2, 4, 1, -1, 0, -1 ], [ -1, 3, 1, -1, 0, -1 ], [ -1, 4, 1, -1, 0, -1 ] ], 3 ] - ], - [ - [ [ [ 0, 4, 1, -1, 0, -1 ], [ -2, 4, 1, -1, 0, -1 ], [ -1, 3, 1, -1, 0, -1 ], [ -2, 4, 1, 0, 0, -1 ] ], 1 ], - [ [ [ 1, 3, 0, -1, 0, -1 ], [ -2, 4, 1, -1, 0, -1 ], [ -1, 3, 1, -1, 0, -1 ], [ -2, 4, 1, 0, 0, -1 ] ], 2.625 ] - ], - [ - [ [ [ 1, 3, 0, -1, 0, -1 ], [ -2, 4, 1, -1, 0, -1 ], [ -1, 3, 1, -1, 0, -1 ], [ -1, 4, 2, -1, 0, -1 ] ], 1 ], - [ [ [ 0, 3, 1, -1, 0, -1 ], [ -2, 4, 1, -1, 0, -1 ], [ -1, 3, 1, -1, 0, -1 ], [ -1, 4, 2, -1, 0, -1 ] ], 1 ], - [ [ [ 0, 3, 1, -1, 0, -1 ], [ -2, 4, 1, -1, 0, -1 ], [ -1, 4, 1, -1, 0, -1 ], [ -1, 4, 2, -1, 0, -1 ] ], 2.75 ] - ], - [ - [ [ [ 0, 3, 1, -1, 0, -1 ], [ -3, 4, 2, 0, 0, -1 ], [ -1, 4, 1, -1, 0, -1 ], [ -1, 4, 2, -1, 0, -1 ] ], 2.375 ] - ], - [ - [ [ [ 0, 3, 1, -1, 0, -1 ], [ -3, 4, 2, 0, 0, -1 ], [ -1, 4, 1, -1, 0, -1 ], [ -1, 4, 2, 0, 0, -2 ] ], 3.375 ] - ], - [ - [ [ [ 0, 3, 1, -1, 0, -1 ], [ -3, 4, 2, 0, 0, -1 ], [ -1, 4, 1, -1, 0, -1 ], [ -1, 3, 2, -1, 0, -1 ] ], 2.875 ] - ], - [ - [ [ [ -1, 5, 1, -1, 0, -1 ], [ -3, 4, 2, 0, 0, -1 ], [ -1, 4, 1, -1, 0, -1 ], [ -1, 3, 2, -1, 0, -1 ] ], 1 ], - [ [ [ -1, 5, 1, -1, 0, -1 ], [ -2, 4, 2, -1, 0, -1 ], [ -1, 4, 1, -1, 0, -1 ], [ -1, 3, 2, -1, 0, -1 ] ], 1 ], - [ [ [ -1, 5, 1, -1, 0, -1 ], [ -2, 4, 2, -1, 0, -1 ], [ -1, 4, 1, -1, 0, -1 ], [ -1, 3, 1, -1, 0, -1 ] ], 1.875 ] - ], - [ - [ [ [ -1, 5, 1, -1, 0, -1 ], [ -2, 4, 1, -1, 0, -1 ], [ -1, 4, 1, -1, 0, -1 ], [ -1, 3, 1, -1, 0, -1 ] ], 3.25 ] - ], - [ - [ [ [ -1, 5, 1, -1, 0, -1 ], [ -2, 5, 1, -1, -1, -1 ], [ -1, 4, 1, -1, 0, -1 ], [ -1, 3, 1, -1, 0, -1 ] ], 1 ], - [ [ [ -1, 5, 1, -1, 0, -1 ], [ -2, 5, 1, -1, -1, -1 ], [ -2, 5, 1, -1, 0, -1 ], [ -1, 3, 1, -1, 0, -1 ] ], 3.625 ] - ], - [ - [ [ [ -1, 5, 1, -1, 0, -1 ], [ -1, 4, 1, -1, 0, -1 ], [ -2, 5, 1, -1, 0, -1 ], [ -1, 3, 1, -1, 0, -1 ] ], 1 ], - [ [ [ -1, 5, 1, -1, 0, -1 ], [ -1, 4, 1, -1, 0, -1 ], [ -2, 5, 1, -1, 0, -1 ], [ -2, 4, 1, -1, 0, -1 ] ], 3.25 ] - ], - [ - [ [ [ -1, 5, 1, -1, 0, -1 ], [ -1, 4, 1, -1, 0, -1 ], [ -2, 5, 1, -1, 0, -1 ], [ -3, 6, 1, -1, 0, -1 ] ], 1.375 ] - ], - [ - [ [ [ -1, 5, 1, -1, 0, -1 ], [ -1, 4, 1, -1, 0, -1 ], [ -3, 7, 1, -1, 0, -1 ], [ -3, 6, 1, -1, 0, -1 ] ], 1.125 ] - ], - [ - [ [ [ -1, 5, 1, -1, 0, -1 ], [ -2, 6, 1, -1, 0, -1 ], [ -3, 7, 1, -1, 0, -1 ], [ -3, 6, 1, -1, 0, -1 ] ], 1.5 ] - ], - [ - [ [ [ -2, 7, 1, -1, 0, -1 ], [ -2, 6, 1, -1, 0, -1 ], [ -3, 7, 1, -1, 0, -1 ], [ -3, 6, 1, -1, 0, -1 ] ], 1 ], - [ [ [ -2, 7, 1, -1, 0, -1 ], [ -2, 6, 1, -1, 0, -1 ], [ -2, 6, 0, -1, 0, -1 ], [ -3, 6, 1, -1, 0, -1 ] ], 2.375 ] - ], - [ - [ [ [ -1, 6, 0, -1, 0, -1 ], [ -2, 6, 1, -1, 0, -1 ], [ -2, 6, 0, -1, 0, -1 ], [ -3, 6, 1, -1, 0, -1 ] ], 3.625 ] - ], - [ - [ [ [ -1, 6, 0, -1, 0, -1 ], [ -2, 6, 1, -1, 0, -1 ], [ -2, 6, 0, -1, 0, -1 ], [ -2, 5, 0, -1, 0, -1 ] ], 1 ], - [ [ [ -4, 6, 1, 0, 0, -1 ], [ -2, 6, 1, -1, 0, -1 ], [ -2, 6, 0, -1, 0, -1 ], [ -2, 5, 0, -1, 0, -1 ] ], 2.125 ] - ], - [ - [ [ [ -3, 6, 1, -1, 0, -1 ], [ -2, 6, 1, -1, 0, -1 ], [ -2, 6, 0, -1, 0, -1 ], [ -2, 5, 0, -1, 0, -1 ] ], 1 ], - [ [ [ -3, 6, 1, -1, 0, -1 ], [ -1, 5, 0, -1, 0, -1 ], [ -2, 6, 0, -1, 0, -1 ], [ -2, 5, 0, -1, 0, -1 ] ], 3.375 ] - ], - [ - [ [ [ -3, 6, 0, -1, 0, -1 ], [ -1, 5, 0, -1, 0, -1 ], [ -2, 6, 0, -1, 0, -1 ], [ -2, 5, 0, -1, 0, -1 ] ], 1 ], - [ [ [ -3, 6, 0, -1, 0, -1 ], [ -1, 5, 0, -1, 0, -1 ], [ -2, 6, 0, -1, 0, -1 ], [ -3, 7, 0, -1, 0, -1 ] ], 1.625 ] - ], - [ - [ [ [ -3, 6, 0, -1, 0, -1 ], [ -1, 5, 0, -1, 0, -1 ], [ -2, 6, 0, -1, 0, -1 ], [ -2, 6, -1, -1, 0, -1 ] ], 1 ], - [ [ [ -3, 6, 0, -1, 0, -1 ], [ -2, 7, 0, -1, 0, -1 ], [ -2, 6, 0, -1, 0, -1 ], [ -2, 6, -1, -1, 0, -1 ] ], 1 ], - [ [ [ -3, 6, 0, -1, 0, -1 ], [ -2, 7, 0, -1, 0, -1 ], [ -2, 6, 0, -1, 1, -1 ], [ -2, 6, -1, -1, 0, -1 ] ], 1.75 ] - ], - [ - [ [ [ -3, 6, 0, -1, 0, -1 ], [ -2, 7, 0, -1, 0, -1 ], [ -2, 6, 0, -1, 1, -1 ], [ -2, 6, 0, -1, 0, -1 ] ], 1 ], - [ [ [ -3, 7, 0, -1, 0, -1 ], [ -2, 7, 0, -1, 0, -1 ], [ -2, 6, 0, -1, 1, -1 ], [ -2, 6, 0, -1, 0, -1 ] ], 2.625 ] - ], - [ - [ [ [ -3, 7, 0, -1, 0, -1 ], [ -2, 7, 0, -1, 0, -1 ], [ -2, 6, 0, -1, 1, -1 ], [ -3, 6, 0, -1, 1, -1 ] ], 1 ], - [ [ [ -2, 6, 0, -1, 1, -2 ], [ -2, 7, 0, -1, 0, -1 ], [ -2, 6, 0, -1, 1, -1 ], [ -3, 6, 0, -1, 1, -1 ] ], 2.25 ] - ], - [ - [ [ [ -2, 6, 0, -1, 1, -2 ], [ -2, 7, 0, -1, 0, -1 ], [ -3, 7, 0, -1, 1, -1 ], [ -3, 6, 0, -1, 1, -1 ] ], 2.125 ] - ], - [ - [ [ [ -2, 6, 0, -1, 1, -2 ], [ -2, 7, -1, -1, 1, -1 ], [ -3, 7, 0, -1, 1, -1 ], [ -3, 6, 0, -1, 1, -1 ] ], 1.375 ] - ], - [ - [ [ [ -3, 6, -1, -1, 1, -1 ], [ -2, 7, -1, -1, 1, -1 ], [ -3, 7, 0, -1, 1, -1 ], [ -3, 6, 0, -1, 1, -1 ] ], 1 ], - [ [ [ -3, 6, -1, -1, 1, -1 ], [ -2, 7, -1, -1, 1, -1 ], [ -3, 7, 0, -1, 1, -1 ], [ -3, 7, -1, -1, 1, -1 ] ], 1.5 ] - ], - [ - [ [ [ -3, 6, -1, -1, 1, -1 ], [ -2, 7, -1, -1, 1, -1 ], [ -2, 6, -1, -1, 1, -1 ], [ -3, 7, -1, -1, 1, -1 ] ], 3.125 ] - ], - [ - [ [ [ -1, 7, -1, -1, 1, -1 ], [ -2, 7, -1, -1, 1, -1 ], [ -2, 6, -1, -1, 1, -1 ], [ -3, 7, -1, -1, 1, -1 ] ], 1 ], - [ [ [ -1, 7, -1, -1, 1, -1 ], [ -2, 7, -1, -1, 1, -1 ], [ -3, 8, -1, -1, 1, -1 ], [ -3, 7, -1, -1, 1, -1 ] ], 2.625 ] - ], - [ - [ [ [ -1, 7, -1, -1, 1, -1 ], [ -2, 7, -1, -2, 1, -1 ], [ -3, 8, -1, -1, 1, -1 ], [ -3, 7, -1, -1, 1, -1 ] ], 1 ], - [ [ [ -2, 9, -1, -1, 1, -1 ], [ -2, 7, -1, -2, 1, -1 ], [ -3, 8, -1, -1, 1, -1 ], [ -3, 7, -1, -1, 1, -1 ] ], 2.625 ] - ], - [ - [ [ [ -2, 9, -1, -1, 1, -1 ], [ -2, 7, -1, -2, 1, -1 ], [ -3, 8, -1, -1, 1, -1 ], [ -4, 9, -1, -1, 1, -1 ] ], 1 ], - [ [ [ -2, 9, -1, -1, 1, -1 ], [ -2, 7, -1, -2, 1, -1 ], [ -4, 10, -1, -1, 1, -1 ], [ -4, 9, -1, -1, 1, -1 ] ], 3.5 ] - ], - [ - [ [ [ -2, 9, -1, -2, 1, -1 ], [ -2, 7, -1, -2, 1, -1 ], [ -4, 10, -1, -1, 1, -1 ], [ -4, 9, -1, -1, 1, -1 ] ], 1 ], - [ [ [ -2, 9, -1, -2, 1, -1 ], [ -4, 8, -1, -1, 1, -1 ], [ -4, 10, -1, -1, 1, -1 ], [ -4, 9, -1, -1, 1, -1 ] ], 3.125 ] - ], - [ - [ [ [ -2, 9, -1, -2, 1, -1 ], [ -4, 8, -1, -1, 1, -1 ], [ -3, 9, -2, -1, 1, -1 ], [ -4, 9, -1, -1, 1, -1 ] ], 1.25 ] - ], - [ - [ [ [ -2, 9, -1, -2, 1, -1 ], [ -4, 8, -1, -1, 1, -1 ], [ -3, 9, -2, -1, 1, -1 ], [ -3, 9, -1, -2, 1, -1 ] ], 3.125 ] - ], - [ - [ [ [ -2, 8, -1, -2, 1, -1 ], [ -4, 8, -1, -1, 1, -1 ], [ -3, 9, -2, -1, 1, -1 ], [ -3, 9, -1, -2, 1, -1 ] ], 1 ], - [ [ [ -2, 8, -1, -2, 1, -1 ], [ -4, 8, -1, -1, 1, -1 ], [ -3, 9, -2, -1, 1, -1 ], [ -3, 8, -1, -2, 1, -1 ] ], 1 ], - [ [ [ -2, 8, -1, -2, 1, -1 ], [ -4, 8, -1, -1, 1, -1 ], [ -3, 8, -1, -1, 1, -1 ], [ -3, 8, -1, -2, 1, -1 ] ], 2.375 ] - ], - [ - [ [ [ -2, 8, -1, -2, 1, -1 ], [ -4, 8, -1, -1, 1, -1 ], [ -3, 8, -1, -1, 1, -1 ], [ -4, 8, 0, -1, 1, -1 ] ], 1 ], - [ [ [ -2, 8, -1, -2, 1, -1 ], [ -4, 8, -1, -1, 1, -1 ], [ -2, 8, -1, -2, 0, -1 ], [ -4, 8, 0, -1, 1, -1 ] ], 2.875 ] - ], - [ - [ [ [ -2, 8, -1, -2, 1, -1 ], [ -4, 8, -1, -1, 1, -1 ], [ -3, 8, -1, -2, 1, 0 ], [ -4, 8, 0, -1, 1, -1 ] ], 1 ], - [ [ [ -2, 8, -1, -2, 1, -1 ], [ -4, 8, -1, -1, 1, -1 ], [ -3, 8, -1, -2, 1, 0 ], [ -3, 8, 0, -2, 1, -1 ] ], 1 ], - [ [ [ -2, 8, -1, -2, 1, -1 ], [ -3, 8, -1, -2, 1, -1 ], [ -3, 8, -1, -2, 1, 0 ], [ -3, 8, 0, -2, 1, -1 ] ], 1.625 ] - ], - [ - [ [ [ -2, 8, -1, -2, 1, -1 ], [ -4, 8, -1, -2, 1, 0 ], [ -3, 8, -1, -2, 1, 0 ], [ -3, 8, 0, -2, 1, -1 ] ], 1 ], - [ [ [ -2, 8, -1, -2, 1, -1 ], [ -4, 8, -1, -2, 1, 0 ], [ -3, 8, -1, -2, 1, 0 ], [ -3, 8, -1, -2, 0, -1 ] ], 1 ], - [ [ [ -2, 8, -1, -2, 1, -1 ], [ -4, 8, -1, -2, 1, 0 ], [ -3, 8, -1, -2, 1, -1 ], [ -3, 8, -1, -2, 0, -1 ] ], 1.875 ] - ], - [ - [ [ [ -2, 7, -1, -2, 1, -1 ], [ -4, 8, -1, -2, 1, 0 ], [ -3, 8, -1, -2, 1, -1 ], [ -3, 8, -1, -2, 0, -1 ] ], 1 ], - [ [ [ -2, 7, -1, -2, 1, -1 ], [ -4, 8, -1, -1, 1, -1 ], [ -3, 8, -1, -2, 1, -1 ], [ -3, 8, -1, -2, 0, -1 ] ], 2.125 ] - ], - [ - [ [ [ -2, 7, -1, -2, 1, -1 ], [ -4, 8, -1, -1, 1, -1 ], [ -2, 8, 0, -2, 0, -1 ], [ -3, 8, -1, -2, 0, -1 ] ], 1 ], - [ [ [ -2, 7, -1, -2, 1, -1 ], [ -3, 8, -1, -2, 1, -1 ], [ -2, 8, 0, -2, 0, -1 ], [ -3, 8, -1, -2, 0, -1 ] ], 1 ], - [ [ [ -2, 8, -1, -2, 0, -1 ], [ -3, 8, -1, -2, 1, -1 ], [ -2, 8, 0, -2, 0, -1 ], [ -3, 8, -1, -2, 0, -1 ] ], 1.75 ] - ], - [ - [ [ [ -3, 8, -1, -2, 1, 0 ], [ -3, 8, -1, -2, 1, -1 ], [ -2, 8, 0, -2, 0, -1 ], [ -3, 8, -1, -2, 0, -1 ] ], 1 ], - [ [ [ -3, 8, -1, -2, 1, 0 ], [ -3, 8, -1, -2, 1, -1 ], [ -2, 8, -1, -2, 1, -1 ], [ -3, 8, -1, -2, 0, -1 ] ], 3.375 ] - ], - [ - [ [ [ -3, 8, -1, -2, 1, 0 ], [ -3, 8, -1, -2, 1, -1 ], [ -2, 8, -1, -2, 1, -1 ], [ -3, 8, -2, -2, 1, -1 ] ], 2.125 ], - [ [ [ -3, 8, -1, -2, 1, 0 ], [ "Rest" ], [ -2, 8, -1, -2, 1, -1 ], [ -3, 8, -2, -2, 1, -1 ] ], 1 ], - [ [ [ -3, 8, -1, -2, 1, 0 ], [ "Rest" ], [ -2, 8, -1, -2, 1, -1 ], [ "Rest" ] ], 1 ], - [ [ [ -3, 8, -1, -2, 1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3.25 ] - ] - ] -], -"last_changes": -[ - [ [ -2, 7, -1, -2, 1, -1 ], [ -3, 8, -1, -2, 1, -1 ], [ -2, 8, 0, -2, 0, -1 ], [ -3, 8, -1, -2, 0, -1 ] ], - [ [ -2, 8, -1, -2, 0, -1 ], [ -3, 8, -1, -2, 1, -1 ], [ -2, 8, 0, -2, 0, -1 ], [ -3, 8, -1, -2, 0, -1 ] ], - [ [ -3, 8, -1, -2, 1, 0 ], [ -3, 8, -1, -2, 1, -1 ], [ -2, 8, 0, -2, 0, -1 ], [ -3, 8, -1, -2, 0, -1 ] ], - [ [ -3, 8, -1, -2, 1, 0 ], [ -3, 8, -1, -2, 1, -1 ], [ -2, 8, -1, -2, 1, -1 ], [ -3, 8, -1, -2, 0, -1 ] ], - [ [ -3, 8, -1, -2, 1, 0 ], [ -3, 8, -1, -2, 1, -1 ], [ -2, 8, -1, -2, 1, -1 ], [ -3, 8, -2, -2, 1, -1 ] ] -], -"cur_uid": "tmp", -"ref_uid": "nil", -"order_seed": 389930, -"dur_seed": 362766, -"motifs_seed": 479673, -"entrances_probs_vals": [ 0, 0, 2.9365079365079, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 2.7380952380952, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 2.7380952380952, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ -1200, 1200, 0.0020576131687243, 0.068181818181818, 0.074074074074074, 0.0625, 0.20576131687243, 0.0625, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.78600823045268, 0.068181818181818, 0.98971193415638, 0.0625 ], -"passages_weights": [ 1, 1, 0.48, 1, 1 ], -"hd_exp": 10, -"hd_invert": 0, -"order": -[ - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 1, 3 ], [ 2, 0 ], [ ] ], - [ [ 0, 3 ], [ 2, 1 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 3, 1 ], [ 2, 0 ], [ ] ], - [ [ 2 ], [ 1, 3, 0 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 0, 3 ], [ 1, 2 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 2 ], [ 0, 3, 1 ], [ ] ], - [ [ 3, 2 ], [ 0, 1 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 2 ], [ 3, 0, 1 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 2, 0 ], [ 3, 1 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 2 ], [ 0, 3, 1 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 1, 3 ], [ 0, 2 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0, 3 ], [ 2, 1 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 2, 3 ], [ 1, 0 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 3, 2 ], [ 0, 1 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 1, 0 ], [ 2, 3 ], [ ] ], - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ], - [ [ 2, 0 ], [ 3, 1 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ], - [ [ 0, 2 ], [ 1, 3 ], [ ] ], - [ [ 0, 2 ], [ 3, 1 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 3, 2 ], [ 0, 1 ], [ ] ], - [ [ 3 ], [ 0, 1, 2 ], [ ] ], - [ [ 3, 0 ], [ 1, 2 ], [ ] ], - [ [ 2 ], [ 3, 0, 1 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 2, 0, 3 ], [ 1 ], [ ] ], - [ [ 3 ], [ 0, 1, 2 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 2 ], [ 0, 3, 1 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 2 ], [ 0, 1, 3 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 0, 3 ], [ 1, 2 ], [ ] ], - [ [ 2, 0 ], [ 1, 3 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 1, 3 ], [ 0, 2 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 1, 2 ], [ 0, 3 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 2, 1 ], [ 0, 3 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 3, 2 ], [ 1, 0 ], [ ] ], - [ [ 0, 1 ], [ 3, 2 ], [ ] ], - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 1 ], [ 0, 3, 2 ], [ ] ], - [ [ 0, 1 ], [ 3, 2 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 100, 100 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise.json deleted file mode 100644 index f1e7021..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise.json +++ /dev/null @@ -1,21 +0,0 @@ -{ -"ledger": -[ - "4874dd07", - "44490863", - "4bf1af12", - "6522664c", - "7ede7adb", - "521654f8", - "6db2efcc", - "4b40ed47", - "4e9f1dcc", - "78a94ed1", - "531df78c", - "7276dc78", - "43214be8", - "7c30c182", - "4ef018fc", - "615c4008" -] -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise.json_bak b/resources/resources_bak_2024_01_03/string_quartet_3_rise.json_bak deleted file mode 100644 index 3b179c3..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise.json_bak +++ /dev/null @@ -1,20 +0,0 @@ -{ -"ledger": -[ - "4874dd07", - "44490863", - "4bf1af12", - "6522664c", - "7ede7adb", - "521654f8", - "6db2efcc", - "4b40ed47", - "4e9f1dcc", - "78a94ed1", - "531df78c", - "7276dc78", - "43214be8", - "7c30c182", - "4ef018fc" -] -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/43214be8_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/43214be8_code.scd deleted file mode 100644 index 42b64ff..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/43214be8_code.scd +++ /dev/null @@ -1,981 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - /* - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - */ - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - //lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - lastState = if(o == 0, {lastXChanges.last.deepCopy}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - /* - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - */ - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - //# voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - # voices, durs = seq.flatten2(if(oneShot, {2}, {3})).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(2).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/43214be8_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/43214be8_mus_model.json deleted file mode 100644 index ec6964f..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/43214be8_mus_model.json +++ /dev/null @@ -1,158 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -7, 6, 4, -1, 1, 2 ], [ -5, 5, 4, 0, 0, 2 ], [ -6, 6, 4, 0, 0, 2 ], [ -6, 6, 4, 0, 1, 2 ] ], 1 ], - [ [ [ -6, 6, 4, -1, 0, 2 ], [ -5, 5, 4, 0, 0, 2 ], [ -6, 6, 4, 0, 0, 2 ], [ -6, 6, 4, 0, 1, 2 ] ], 1 ], - [ [ [ -6, 6, 4, -1, 0, 2 ], [ -5, 5, 4, 0, 0, 2 ], [ -6, 6, 4, 0, 0, 2 ], [ -7, 6, 5, 0, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 6, 4, -1, 0, 2 ], [ -5, 6, 3, 0, 0, 2 ], [ -6, 6, 4, 0, 0, 2 ], [ -7, 6, 5, 0, 0, 2 ] ], 1 ], - [ [ [ -6, 6, 4, -1, 0, 2 ], [ -5, 6, 3, 0, 0, 2 ], [ -6, 6, 4, 0, 0, 2 ], [ -7, 6, 4, 1, 0, 2 ] ], 1 ], - [ [ [ -6, 6, 3, 0, 0, 2 ], [ -5, 6, 3, 0, 0, 2 ], [ -6, 6, 4, 0, 0, 2 ], [ -7, 6, 4, 1, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 6, 3, 0, 0, 2 ], [ -5, 6, 3, 0, 0, 2 ], [ -5, 6, 2, 0, 0, 2 ], [ -7, 6, 4, 1, 0, 2 ] ], 1 ], - [ [ [ -6, 6, 3, 0, 0, 2 ], [ -5, 6, 3, 0, 0, 2 ], [ -5, 6, 2, 0, 0, 2 ], [ -6, 7, 3, 0, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 6, 3, 0, 0, 2 ], [ -5, 6, 2, -1, 0, 2 ], [ -5, 6, 2, 0, 0, 2 ], [ -6, 7, 3, 0, 0, 2 ] ], 1 ], - [ [ [ -6, 6, 2, 1, 0, 2 ], [ -5, 6, 2, -1, 0, 2 ], [ -5, 6, 2, 0, 0, 2 ], [ -6, 7, 3, 0, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 6, 2, 1, 0, 2 ], [ -5, 6, 2, -1, 0, 2 ], [ -6, 7, 2, 1, 0, 2 ], [ -6, 7, 3, 0, 0, 2 ] ], 1 ], - [ [ [ -6, 6, 2, 1, 0, 2 ], [ -7, 6, 2, 2, 0, 2 ], [ -6, 7, 2, 1, 0, 2 ], [ -6, 7, 3, 0, 0, 2 ] ], 1 ], - [ [ [ -6, 6, 2, 1, 0, 2 ], [ -7, 6, 2, 2, 0, 2 ], [ -6, 7, 2, 1, 0, 2 ], [ -5, 6, 2, 1, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 6, 2, 1, 0, 2 ], [ -7, 6, 2, 2, 0, 2 ], [ -5, 6, 2, 1, -1, 1 ], [ -5, 6, 2, 1, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 6, 2, 1, 0, 2 ], [ -7, 6, 2, 2, 0, 2 ], [ -6, 6, 2, 2, -1, 2 ], [ -5, 6, 2, 1, -1, 2 ] ], 1 ], - [ [ [ -6, 6, 2, 1, 0, 2 ], [ -7, 6, 2, 2, 0, 2 ], [ -6, 6, 2, 2, -1, 2 ], [ -7, 5, 2, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 6, 2, 1, 0, 2 ], [ -7, 6, 2, 2, 0, 2 ], [ -7, 5, 2, 3, 0, 2 ], [ -7, 5, 2, 2, 0, 2 ] ], 1 ], - [ [ [ -8, 6, 2, 2, 0, 2 ], [ -7, 6, 2, 2, 0, 2 ], [ -7, 5, 2, 3, 0, 2 ], [ -7, 5, 2, 2, 0, 2 ] ], 1 ], - [ [ [ -8, 6, 2, 2, 0, 2 ], [ -7, 5, 2, 2, -1, 2 ], [ -7, 5, 2, 3, 0, 2 ], [ -7, 5, 2, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 6, 2, 2, -1, 2 ], [ -7, 5, 2, 2, -1, 2 ], [ -7, 5, 2, 3, 0, 2 ], [ -7, 5, 2, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 6, 2, 2, -1, 2 ], [ -7, 5, 2, 2, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -7, 5, 2, 2, 0, 2 ] ], 1 ], - [ [ [ -7, 6, 2, 2, -1, 2 ], [ -6, 6, 2, 2, -2, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -7, 5, 2, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 6, 2, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -7, 5, 2, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 6, 2, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 2, 2, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 6, 2, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 6, 2, 2, -1, 2 ] ], 1 ], - [ [ [ -6, 5, 1, 2, 0, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 6, 2, 2, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 5, 1, 2, 0, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -5, 5, 0, 2, 0, 2 ], [ -6, 6, 2, 2, -1, 2 ] ], 1 ], - [ [ [ -6, 5, 1, 2, 0, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -5, 5, 0, 2, 0, 2 ], [ -6, 6, 1, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 5, 1, 2, 0, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -7, 6, 2, 2, 0, 2 ], [ -6, 6, 1, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 5, 1, 3, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -7, 6, 2, 2, 0, 2 ], [ -6, 6, 1, 2, 0, 2 ] ], 1 ], - [ [ [ -6, 5, 1, 3, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 5, 1, 2, -2, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 5, 1, 2, -2, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ] ], 1 ], - [ [ [ -7, 5, 1, 2, -2, 2 ], [ -7, 5, 1, 3, -2, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ] ], 1 ], - [ [ [ -7, 5, 1, 2, -1, 2 ], [ -7, 5, 1, 3, -2, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 5, 1, 2, -1, 2 ], [ -7, 5, 1, 3, -2, 2 ], [ -5, 5, 1, 1, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ] ], 1 ], - [ [ [ -6, 5, 1, 2, -2, 2 ], [ -7, 5, 1, 3, -2, 2 ], [ -5, 5, 1, 1, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ] ], 1 ], - [ [ [ -6, 5, 1, 2, -2, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -5, 5, 1, 1, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -8, 5, 0, 3, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -5, 5, 1, 1, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ] ], 1 ], - [ [ [ -8, 5, 0, 3, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 6, 1, 2, -2, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 6, 1, 2, -2, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -7, 6, 1, 3, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -8, 4, 1, 3, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -7, 6, 1, 3, -1, 2 ] ], 1 ], - [ [ [ -8, 4, 1, 3, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 1, 3, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -9, 5, 1, 4, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 1, 3, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -9, 5, 1, 4, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 1, 4, -2, 2 ] ], 1 ], - [ [ [ -9, 5, 1, 4, -1, 2 ], [ -7, 5, 1, 4, -2, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 1, 4, -2, 2 ] ], 1 ] - ] - ] -], -"last_changes": -[ - [ [ -9, 8, 0, 5, -2, 2 ], [ -8, 7, 0, 5, -2, 2 ], [ -9, 7, 1, 5, -2, 2 ], [ -8, 7, 1, 5, -2, 2 ] ], - [ [ -9, 8, 0, 5, -2, 2 ], [ -8, 7, 0, 5, -2, 2 ], [ -9, 7, 1, 5, -2, 2 ], [ -9, 7, 0, 6, -2, 2 ] ], - [ [ -9, 8, 0, 5, -2, 2 ], [ -8, 7, 0, 5, -2, 2 ], [ -9, 7, 0, 5, -2, 2 ], [ -9, 7, 0, 6, -2, 2 ] ], - [ [ -9, 8, 0, 5, -2, 2 ], [ -8, 7, 0, 5, -2, 2 ], [ -9, 7, 0, 5, -2, 2 ], [ -7, 7, 0, 4, -2, 2 ] ], - [ [ -8, 7, -1, 5, -2, 2 ], [ -8, 7, 0, 5, -2, 2 ], [ -9, 7, 0, 5, -2, 2 ], [ -7, 7, 0, 4, -2, 2 ] ] -], -"cur_uid": "43214be8", -"ref_uid": "7276dc78", -"order_seed": 553436, -"dur_seed": 804010, -"motifs_seed": 337121, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ 0, 1200, 0.0061728395061728, 0.10227272727273, 0.074074074074074, 0.10227272727273, 0.2037037037037, 0.090909090909091, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.7880658436214, 0.034090909090909, 1, 0.034090909090909 ], -"passages_weights": [ 0.08, 0.47, 0.43, 1, 1 ], -"hd_exp": 10, -"hd_invert": 0, -"order": -[ - [ [ 3 ], [ 1, 2, 0 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 1 ], [ 3, 2, 0 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 2, 0, 3 ], [ 1 ], [ ] ], - [ [ 1 ], [ 2, 3, 0 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 2 ], [ 3, 0, 1 ], [ ] ], - [ [ 3 ], [ 0, 1, 2 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 1 ], [ 2, 0, 3 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 1, 3 ], [ 2, 0 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 0, 3, 1 ], [ 2 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 3 ], [ 0, 2, 1 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 2 ], [ 0, 3, 1 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 1 ], [ 2, 3, 0 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 25, 25.244897959184 ], -"passages_size": [ 0, 0 ], -"motif_edited": "true", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/lilypond/part_I.ly deleted file mode 100644 index e9eae1a..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/lilypond/part_I.ly +++ /dev/null @@ -1,48 +0,0 @@ -{ - { gis'1^\markup { \pad-markup #0.2 "-11"} } - \bar "|" - { fis1^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }} } - \bar "|" - { c'1^\markup { \pad-markup #0.2 "+7"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }} ~ } - \bar "|" - { c'2 fis'2^\markup { \pad-markup #0.2 "-46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 } - \bar "|" - { b'1^\markup { \pad-markup #0.2 "-17"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }} ~ } - \bar "|" - { b'2 g2^\markup { \pad-markup #0.2 "+1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g2 cis'2^\markup { \pad-markup #0.2 "+50"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} } - \bar "|" - { a'1^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { a'2 ais'2^\markup { \pad-markup #0.2 "+17"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 } - \bar "|" - { ais1^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais2 d'2^\markup { \pad-markup #0.2 "+34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { d'2 g'2^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { g'2 b'2^\markup { \pad-markup #0.2 "+50"}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/lilypond/part_II.ly deleted file mode 100644 index bd2901a..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/lilypond/part_II.ly +++ /dev/null @@ -1,48 +0,0 @@ -{ - { d'1^\markup { \pad-markup #0.2 "+38"} ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'1 } - \bar "|" - { g'1^\markup { \pad-markup #0.2 "-35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { g'1 } - \bar "|" - { b'1^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { b'2 d'2^\markup { \pad-markup #0.2 "+42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↓" }} } - \bar "|" - { a'1^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↓" }} } - \bar "|" - { f'1^\markup { \pad-markup #0.2 "-30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }} ~ } - \bar "|" - { f'1 } - \bar "|" - { f'1^\markup { \pad-markup #0.2 "-35"} ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 } - \bar "|" - { b'1^\markup { \pad-markup #0.2 "+28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} } - \bar "|" - { d'1^\markup { \pad-markup #0.2 "+3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }} } - \bar "|" - { g1^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g2 c'2^\markup { \pad-markup #0.2 "-5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }} ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'2 f'2^\markup { \pad-markup #0.2 "-35"} ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/lilypond/part_III.ly deleted file mode 100644 index 192a5db..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/lilypond/part_III.ly +++ /dev/null @@ -1,48 +0,0 @@ -{ - { g'1^\markup { \pad-markup #0.2 "+36"} ~ } - \bar "|" - { g'2 b'2^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }} ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 } - \bar "|" - { a1^\markup { \pad-markup #0.2 "-3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }} ~ } - \bar "|" - { a2 d'2^\markup { \pad-markup #0.2 "+3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }} ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'1 } - \bar "|" - { cis1^\markup { \pad-markup #0.2 "+50"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }} ~ } - \bar "|" - { cis2 dis'2^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }} } - \bar "|" - { ais'1^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }} ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'2 d2^\markup { \pad-markup #0.2 "-19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }} ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d2 g2^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }} ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/lilypond/part_IV.ly deleted file mode 100644 index 534e787..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/43214be8/lilypond/part_IV.ly +++ /dev/null @@ -1,48 +0,0 @@ -{ - { ais,2^\markup { \pad-markup #0.2 "+21"} f2^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }} ~ } - \bar "|" - { f1 ~ } - \bar "|" - { f2 b2^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b2 e'2^\markup { \pad-markup #0.2 "+34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }} ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'2 d2^\markup { \pad-markup #0.2 "+3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { d2 a2^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a2 dis'2^\markup { \pad-markup #0.2 "+15"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↑" }} ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'2 g'2^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }} ~ } - \bar "|" - { g'2 e,2^\markup { \pad-markup #0.2 "+12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↓" }} ~ } - \bar "|" - { e,1 } - \bar "|" - { ais,1^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} } - \bar "|" - { e1^\markup { \pad-markup #0.2 "+12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }} } - \bar "|" - { dis,1^\markup { \pad-markup #0.2 "+46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }} } - \bar "|" - { b,1^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↓" }} } - \bar "|" - { c,1^\markup { \pad-markup #0.2 "+30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} } - \bar "|" - { f,1^\markup { \pad-markup #0.2 "+1"}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/44490863_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/44490863_code.scd deleted file mode 100644 index 23ccdf1..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/44490863_code.scd +++ /dev/null @@ -1,981 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - /* - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - */ - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - //lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - lastState = if(o == 0, {lastXChanges.last.deepCopy}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - /* - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - */ - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - //# voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - # voices, durs = seq.flatten2(if(oneShot, {2}, {3})).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/44490863_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/44490863_mus_model.json deleted file mode 100644 index b1d0e34..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/44490863_mus_model.json +++ /dev/null @@ -1,154 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -1, 2, 0, 0, 1, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 1, 1, 0, 0, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 1, 1, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 1, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 0, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 0, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 2, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 2, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ], [ -1, 2, 1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 2, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ], [ 1, 0, 1, -1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 2, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ], [ 0, 0, 2, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 2, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ], [ 0, 0, 2, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 2, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 1, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 1, 0, 0, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 1, 1, 0, 0, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ], [ -2, 2, 1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 1, 0, 0, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -2, 3, 1, 0, 0, 0 ], [ -2, 2, 1, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 2, 0, 0, 0, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -2, 3, 1, 0, 0, 0 ], [ -2, 2, 1, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 2, 0, 0, 0, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -2, 3, 1, 0, 0, 0 ], [ -2, 2, 2, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 2, 0, 0, 0, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ -2, 2, 2, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 2, 1, 0, 0, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ -2, 2, 2, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 2, 1, 0, 0, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ -2, 3, 1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 4, 1, 0, 0, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ -2, 3, 1, 0, 0, 0 ] ], 1 ], - [ [ [ -3, 4, 1, 0, 0, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -2, 3, 2, 0, 0, 0 ], [ -2, 3, 1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 4, 1, 0, 0, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -2, 3, 2, 0, 0, 0 ], [ -2, 4, 2, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 2, 2, 0, 0, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -2, 3, 2, 0, 0, 0 ], [ -2, 4, 2, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 2, 2, 0, 0, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -1, 2, 1, 0, 1, 0 ], [ -2, 4, 2, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 3, 1, 0, 0, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -1, 2, 1, 0, 1, 0 ], [ -2, 4, 2, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 3, 1, 0, 0, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -1, 2, 1, 0, 1, 0 ], [ -2, 2, 1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 3, 1, 0, 0, 0 ], [ -2, 3, 1, 0, 1, 0 ], [ -1, 2, 1, 0, 1, 0 ], [ -2, 2, 1, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 3, 1, 0, 0, 0 ], [ -2, 3, 1, 0, 1, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -2, 2, 1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 3, 2, 0, 1, 0 ], [ -2, 3, 1, 0, 1, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -2, 2, 1, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 3, 2, 0, 1, 0 ], [ -2, 3, 1, 0, 1, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -2, 3, 1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 3, 2, 0, 1, 0 ], [ -2, 3, 1, 0, 1, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -1, 2, 1, 0, 1, 0 ] ], 1 ], - [ [ [ -2, 2, 1, 0, 1, 0 ], [ -2, 3, 1, 0, 1, 0 ], [ -1, 2, 1, 0, 0, 0 ], [ -1, 2, 1, 0, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 2, 1, 0, 1, 0 ], [ -2, 3, 1, 0, 1, 0 ], [ -1, 2, 0, 0, 1, 0 ], [ -1, 2, 1, 0, 1, 0 ] ], 1 ], - [ [ [ -2, 2, 1, 0, 1, 0 ], [ -2, 2, 1, 1, 1, 0 ], [ -1, 2, 0, 0, 1, 0 ], [ -1, 2, 1, 0, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 2, 1, 0, 1, 0 ], [ -2, 2, 1, 1, 1, 0 ], [ -1, 2, 0, 0, 1, 0 ], [ -3, 2, 1, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 2, 1, 0, 1, 0 ], [ -1, 2, 1, 0, 1, 0 ], [ -1, 2, 0, 0, 1, 0 ], [ -3, 2, 1, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 2, 1, 0, 1, 0 ], [ -1, 2, 1, 0, 1, 0 ], [ -2, 2, 1, 1, 1, 0 ], [ -3, 2, 1, 1, 1, 0 ] ], 1 ], - [ [ [ -2, 1, 1, 1, 1, 0 ], [ -1, 2, 1, 0, 1, 0 ], [ -2, 2, 1, 1, 1, 0 ], [ -3, 2, 1, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 1, 1, 1, 0 ], [ -1, 2, 1, 0, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 2, 1, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 1, 1, 1, 0 ], [ -1, 2, 1, 0, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ], - [ [ [ -2, 1, 1, 1, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 1, 1, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ], - [ [ [ -2, 0, 2, 2, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 1, 2, 2, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ] - ] - ] -], -"last_changes": -[ - [ [ -2, 1, 1, 1, 1, 0 ], [ -1, 2, 1, 0, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], - [ [ -2, 1, 1, 1, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], - [ [ -2, 1, 1, 1, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], - [ [ -2, 0, 2, 2, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], - [ [ -5, 1, 2, 2, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ] -], -"cur_uid": "44490863", -"ref_uid": "4874dd07", -"order_seed": 903957, -"dur_seed": 360025, -"motifs_seed": 692248, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ 0, 1200, 0.0061728395061728, 0.10227272727273, 0.074074074074074, 0.10227272727273, 0.2037037037037, 0.090909090909091, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.7880658436214, 0.034090909090909, 1, 0.034090909090909 ], -"passages_weights": [ 1, 0.47, 0.43, 1, 1 ], -"hd_exp": 10, -"hd_invert": 0, -"order": -[ - [ [ 3, 2 ], [ 1, 0 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 3 ], [ 1, 0, 2 ], [ ] ], - [ [ 1, 2 ], [ 0, 3 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 0, 1 ], [ 3, 2 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 0, 2 ], [ 1, 3 ], [ ] ], - [ [ 1 ], [ 2, 0, 3 ], [ ] ], - [ [ 1 ], [ 2, 0, 3 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 1 ], [ 2, 0, 3 ], [ ] ], - [ [ 3, 0 ], [ 1, 2 ], [ ] ], - [ [ 1, 2 ], [ 0, 3 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 0, 3 ], [ 2, 1 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 2, 0, 3 ], [ 1 ], [ ] ], - [ [ 1, 3 ], [ 2, 0 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 2, 0 ], [ 3, 1 ], [ ] ], - [ [ 1, 3 ], [ 2, 0 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 5.0408163265306, 25.244897959184 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/lilypond/part_I.ly deleted file mode 100644 index a351af0..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/lilypond/part_I.ly +++ /dev/null @@ -1,48 +0,0 @@ -{ - { b1^\markup { \pad-markup #0.2 "-12"} ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b2 fis'2^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} } - \bar "|" - { fis'2^\markup { \pad-markup #0.2 "+17"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }} gis'2^\markup { \pad-markup #0.2 "-27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }} ~ } - \bar "|" - { gis'2 b'2^\markup { \pad-markup #0.2 "-12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } - \bar "|" - { b'1 } - \bar "|" - { fis1^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { fis2 ais2^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }} ~ } - \bar "|" - { ais1 } - \bar "|" - { cis'1^\markup { \pad-markup #0.2 "-8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { cis'2 c''2^\markup { \pad-markup #0.2 "-20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''2 fis2^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis2 cis'2^\markup { \pad-markup #0.2 "-8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↓" }} } - \bar "|" - { b'1^\markup { \pad-markup #0.2 "+42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } - \bar "|" - { b'1 } - \bar "|" - { a1^\markup { \pad-markup #0.2 "+10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a2 e'2^\markup { \pad-markup #0.2 "-36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }} ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/lilypond/part_II.ly deleted file mode 100644 index 93d3bf8..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/lilypond/part_II.ly +++ /dev/null @@ -1,48 +0,0 @@ -{ - { g'1^\markup { \pad-markup #0.2 "+2"} ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'2 b'2^\markup { \pad-markup #0.2 "-12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 } - \bar "|" - { b1^\markup { \pad-markup #0.2 "-12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b2 cis'2^\markup { \pad-markup #0.2 "-8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { cis'1 } - \bar "|" - { d'1^\markup { \pad-markup #0.2 "+4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { d'1 } - \bar "|" - { f'1^\markup { \pad-markup #0.2 "-22"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }} ~ } - \bar "|" - { f'2 b'2^\markup { \pad-markup #0.2 "+42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↑" }} ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'2 fis'2^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 } - \bar "|" - { gis'1^\markup { \pad-markup #0.2 "-45"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { gis'1 } - \bar "|" - { a'1^\markup { \pad-markup #0.2 "+10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} } - \bar "|" - { c''1^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }} ~ } - \bar "|" - { c''2 b'2^\markup { \pad-markup #0.2 "-34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }} ~ } - \bar "|" - { b'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/lilypond/part_III.ly deleted file mode 100644 index 606adf0..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/lilypond/part_III.ly +++ /dev/null @@ -1,48 +0,0 @@ -{ - { fis'1^\markup { \pad-markup #0.2 "-10"} } - \bar "|" - { g2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} e'2^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'2 fis'2^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 } - \bar "|" - { fis'1^\markup { \pad-markup #0.2 "+43"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }} ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'2 a'2^\markup { \pad-markup #0.2 "+10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }} ~ } - \bar "|" - { a'2 b'2^\markup { \pad-markup #0.2 "+42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 } - \bar "|" - { g1^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }} ~ } - \bar "|" - { g1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/lilypond/part_IV.ly deleted file mode 100644 index b3eb4c8..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/44490863/lilypond/part_IV.ly +++ /dev/null @@ -1,48 +0,0 @@ -{ - { gis'2^\markup { \pad-markup #0.2 "-45"} b'2^\markup { \pad-markup #0.2 "-12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { b'1 } - \bar "|" - { e1^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} } - \bar "|" - { fis1^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }} ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 } - \bar "|" - { b,1^\markup { \pad-markup #0.2 "-12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } - \bar "|" - { b,1 } - \bar "|" - { d1^\markup { \pad-markup #0.2 "+4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }} ~ } - \bar "|" - { d2 fis2^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { fis2 gis2^\markup { \pad-markup #0.2 "-6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }} ~ } - \bar "|" - { gis1 } - \bar "|" - { ais1^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }} } - \bar "|" - { cis'1^\markup { \pad-markup #0.2 "-8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { cis'1 } - \bar "|" - { ais'1^\markup { \pad-markup #0.2 "+30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }} ~ } - \bar "|" - { ais'2 b2^\markup { \pad-markup #0.2 "+42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b2 d'2^\markup { \pad-markup #0.2 "+8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }} ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'1 } - \bar "|" - { a'2^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }} e,2^\markup { \pad-markup #0.2 "-36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/4874dd07_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/4874dd07_code.scd deleted file mode 100644 index c4e3d1b..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/4874dd07_code.scd +++ /dev/null @@ -1,979 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - /* - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - */ - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - /* - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - */ - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/4874dd07_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/4874dd07_mus_model.json deleted file mode 100644 index 74fb11d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/4874dd07_mus_model.json +++ /dev/null @@ -1,121 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 2, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 2, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 2, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ -2, 3, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 2, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ -1, 3, 0, 0, 0, 0 ], [ -2, 3, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 2, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ -1, 3, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ] ], 1 ], - [ [ [ -1, 2, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 2, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ] ], 1 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ] ], 1 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 1, -1, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, -1, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 1, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ] ], 1 ], - [ [ [ 1, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, -1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, -1, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 1, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 1, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 2, 1, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 2, 0, 0, 1, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ] ], 1 ] - ] - ] -], -"last_changes": -[ - [ [ 0, -1, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], - [ [ -1, 1, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ] ], - [ [ -1, 1, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ] ], - [ [ -1, 2, 1, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ] ], - [ [ -1, 2, 0, 0, 1, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ] ] -], -"cur_uid": "4874dd07", -"ref_uid": "nil", -"order_seed": 701987, -"dur_seed": 150121, -"motifs_seed": 970221, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ 0, 1200, 0.0061728395061728, 0.10227272727273, 0.074074074074074, 0.10227272727273, 0.2037037037037, 0.090909090909091, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.7880658436214, 0.034090909090909, 1, 0.034090909090909 ], -"passages_weights": [ 1, 0.47, 0.43, 1, 1 ], -"hd_exp": 10, -"hd_invert": 0, -"order": -[ - [ [ 0, 3 ], [ 1, 2 ], [ ] ], - [ [ 2, 1 ], [ 0, 3 ], [ ] ], - [ [ 0, 1 ], [ 3, 2 ], [ ] ], - [ [ 1, 0 ], [ 3, 2 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 3 ], [ 0, 2, 1 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 3 ], [ 1, 2, 0 ], [ ] ], - [ [ 1 ], [ 3, 2, 0 ], [ ] ], - [ [ 2, 0 ], [ 1, 3 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 2, 3 ], [ 1, 0 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 4.8265306122449, 25 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/lilypond/part_I.ly deleted file mode 100644 index 63f4a0e..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/lilypond/part_I.ly +++ /dev/null @@ -1,38 +0,0 @@ -{ - { r2 c'2^\markup { \pad-markup #0.2 "+0"} ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'2 g2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} } - \bar "|" - { a1^\markup { \pad-markup #0.2 "+6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} } - \bar "|" - { ais1^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }} ~ } - \bar "|" - { ais1 } - \bar "|" - { c'1^\markup { \pad-markup #0.2 "+0"} ~ } - \bar "|" - { c'2 f'2^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 } - \bar "|" - { g'1^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 } - \bar "|" - { ais'1^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }} ~ } - \bar "|" - { ais'1 } - \bar "|" - { c''1^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { c''1 } - \bar "|" - { b1^\markup { \pad-markup #0.2 "-12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/lilypond/part_II.ly deleted file mode 100644 index 8b4aa3d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/lilypond/part_II.ly +++ /dev/null @@ -1,38 +0,0 @@ -{ - { r1 } - \bar "|" - { r2 g'2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'2 a'2^\markup { \pad-markup #0.2 "+6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { a'2 c''2^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''2 g'2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'2 c''2^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''1 } - \bar "|" - { f1^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} } - \bar "|" - { c'1^\markup { \pad-markup #0.2 "+0"} ~ } - \bar "|" - { c'2 g'2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/lilypond/part_III.ly deleted file mode 100644 index f3dc391..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/lilypond/part_III.ly +++ /dev/null @@ -1,38 +0,0 @@ -{ - { r1 } - \bar "|" - { c1^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 } - \bar "|" - { g1^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { g1 } - \bar "|" - { gis1^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { gis1 } - \bar "|" - { c'1^\markup { \pad-markup #0.2 "+0"} ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'2 c2^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c2 g2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } - \bar "|" - { g1 } - \bar "|" - { d'1^\markup { \pad-markup #0.2 "+4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }} ~ } - \bar "|" - { d'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/lilypond/part_IV.ly deleted file mode 100644 index c4f4ab6..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4874dd07/lilypond/part_IV.ly +++ /dev/null @@ -1,38 +0,0 @@ -{ - { c'1^\markup { \pad-markup #0.2 "+0"} ~ } - \bar "|" - { c'1 } - \bar "|" - { d'1^\markup { \pad-markup #0.2 "+4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }} ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'2 c2^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 } - \bar "|" - { f1^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { f2 g2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { g2 f'2^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'2 c''2^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { c''1 } - \bar "|" - { c'1^\markup { \pad-markup #0.2 "+0"} ~ } - \bar "|" - { c'2 f2^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }} ~ } - \bar "|" - { f2 g2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } - \bar "|" - { g2 fis'2^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/4b40ed47_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/4b40ed47_code.scd deleted file mode 100644 index 42b64ff..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/4b40ed47_code.scd +++ /dev/null @@ -1,981 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - /* - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - */ - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - //lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - lastState = if(o == 0, {lastXChanges.last.deepCopy}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - /* - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - */ - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - //# voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - # voices, durs = seq.flatten2(if(oneShot, {2}, {3})).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(2).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/4b40ed47_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/4b40ed47_mus_model.json deleted file mode 100644 index 85dcea4..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/4b40ed47_mus_model.json +++ /dev/null @@ -1,86 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -4, 2, 4, 2, 1, 0 ], [ -3, 2, 3, 2, 1, -1 ], [ -4, 2, 3, 2, 1, 0 ], [ -3, 2, 3, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 2, 4, 2, 1, 0 ], [ -3, 2, 3, 2, 1, -1 ], [ -5, 2, 4, 2, 1, 1 ], [ -3, 2, 3, 2, 0, 0 ] ], 1 ], - [ [ [ -4, 2, 4, 2, 1, 0 ], [ -3, 2, 3, 2, 1, -1 ], [ -5, 2, 4, 2, 1, 1 ], [ -3, 2, 3, 2, 2, -1 ] ], 1 ] - ], - [ - [ [ [ -4, 2, 4, 2, 1, 0 ], [ -4, 1, 4, 2, 1, 1 ], [ -5, 2, 4, 2, 1, 1 ], [ -3, 2, 3, 2, 2, -1 ] ], 1 ], - [ [ [ -5, 2, 5, 2, 1, 1 ], [ -4, 1, 4, 2, 1, 1 ], [ -5, 2, 4, 2, 1, 1 ], [ -3, 2, 3, 2, 2, -1 ] ], 1 ], - [ [ [ -5, 2, 5, 2, 1, 1 ], [ -4, 1, 4, 2, 1, 1 ], [ -5, 2, 4, 2, 1, 1 ], [ -5, 1, 4, 2, 1, 1 ] ], 1 ] - ], - [ - [ [ [ -5, 2, 5, 2, 1, 1 ], [ -4, 1, 4, 2, 1, 1 ], [ -3, 1, 4, 2, 1, 0 ], [ -5, 1, 4, 2, 1, 1 ] ], 1 ] - ], - [ - [ [ [ -5, 2, 5, 2, 1, 1 ], [ -4, 1, 4, 2, 1, 1 ], [ -3, 1, 4, 2, 1, 0 ], [ -5, 1, 4, 3, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 2, 5, 2, 1, 1 ], [ -4, 1, 4, 2, 1, 1 ], [ -4, 1, 5, 2, 1, 1 ], [ -5, 1, 4, 3, 1, 0 ] ], 1 ], - [ [ [ -5, 1, 4, 4, 1, 0 ], [ -4, 1, 4, 2, 1, 1 ], [ -4, 1, 5, 2, 1, 1 ], [ -5, 1, 4, 3, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 1, 4, 4, 1, 0 ], [ -4, 1, 4, 2, 1, 1 ], [ -6, 1, 4, 3, 1, 1 ], [ -5, 1, 4, 3, 1, 0 ] ], 1 ], - [ [ [ -5, 1, 4, 4, 1, 0 ], [ -4, 1, 4, 2, 1, 1 ], [ -6, 1, 4, 3, 1, 1 ], [ -4, 1, 4, 2, 1, 0 ] ], 1 ], - [ [ [ -5, 2, 4, 2, 1, 1 ], [ -4, 1, 4, 2, 1, 1 ], [ -6, 1, 4, 3, 1, 1 ], [ -4, 1, 4, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 2, 4, 2, 1, 1 ], [ -4, 1, 4, 3, 1, 0 ], [ -6, 1, 4, 3, 1, 1 ], [ -4, 1, 4, 2, 1, 0 ] ], 1 ], - [ [ [ -4, 1, 5, 2, 1, 0 ], [ -4, 1, 4, 3, 1, 0 ], [ -6, 1, 4, 3, 1, 1 ], [ -4, 1, 4, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 0, 4, 3, 1, 1 ], [ -4, 1, 4, 3, 1, 0 ], [ -6, 1, 4, 3, 1, 1 ], [ -4, 1, 4, 2, 1, 0 ] ], 1 ], - [ [ [ -4, 0, 4, 3, 1, 1 ], [ -4, 1, 4, 3, 0, 1 ], [ -6, 1, 4, 3, 1, 1 ], [ -4, 1, 4, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 0, 4, 3, 1, 1 ], [ -4, 1, 4, 3, 0, 1 ], [ -5, 1, 4, 2, 1, 1 ], [ -4, 1, 4, 2, 1, 0 ] ], 1 ], - [ [ [ -4, 0, 4, 3, 1, 1 ], [ -3, 1, 4, 1, 1, 0 ], [ -5, 1, 4, 2, 1, 1 ], [ -4, 1, 4, 2, 1, 0 ] ], 1 ], - [ [ [ -3, 1, 4, 2, 1, 0 ], [ -3, 1, 4, 1, 1, 0 ], [ -5, 1, 4, 2, 1, 1 ], [ -4, 1, 4, 2, 1, 0 ] ], 1 ] - ] - ] -], -"last_changes": -[ - [ [ -4, 0, 4, 3, 1, 1 ], [ -4, 1, 4, 3, 1, 0 ], [ -6, 1, 4, 3, 1, 1 ], [ -4, 1, 4, 2, 1, 0 ] ], - [ [ -4, 0, 4, 3, 1, 1 ], [ -4, 1, 4, 3, 0, 1 ], [ -6, 1, 4, 3, 1, 1 ], [ -4, 1, 4, 2, 1, 0 ] ], - [ [ -4, 0, 4, 3, 1, 1 ], [ -4, 1, 4, 3, 0, 1 ], [ -5, 1, 4, 2, 1, 1 ], [ -4, 1, 4, 2, 1, 0 ] ], - [ [ -4, 0, 4, 3, 1, 1 ], [ -3, 1, 4, 1, 1, 0 ], [ -5, 1, 4, 2, 1, 1 ], [ -4, 1, 4, 2, 1, 0 ] ], - [ [ -3, 1, 4, 2, 1, 0 ], [ -3, 1, 4, 1, 1, 0 ], [ -5, 1, 4, 2, 1, 1 ], [ -4, 1, 4, 2, 1, 0 ] ] -], -"cur_uid": "4b40ed47", -"ref_uid": "6db2efcc", -"order_seed": 401316, -"dur_seed": 325935, -"motifs_seed": 749229, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ 0, 1200, 0.0061728395061728, 0.10227272727273, 0.074074074074074, 0.10227272727273, 0.2037037037037, 0.090909090909091, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.7880658436214, 0.034090909090909, 1, 0.034090909090909 ], -"passages_weights": [ 1, 0.47, 0.43, 1, 0.4 ], -"hd_exp": 4, -"hd_invert": 0, -"order": -[ - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 0, 1 ], [ 2, 3 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 1, 3 ], [ 2, 0 ], [ ] ], - [ [ 1 ], [ 2, 3, 0 ], [ ] ], - [ [ 3, 2 ], [ 1, 0 ], [ ] ], - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 10.091836734694, 10.091836734694 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/lilypond/part_I.ly deleted file mode 100644 index 669e421..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/lilypond/part_I.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { a'1^\markup { \pad-markup #0.2 "+1"} } - \bar "|" - { c''1^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↑" }} ~ } - \bar "|" - { c''2 gis2^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { gis2 a2^\markup { \pad-markup #0.2 "+5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }} ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a2 b2^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↓" }} ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/lilypond/part_II.ly deleted file mode 100644 index 1c18623..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/lilypond/part_II.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { dis'2^\markup { \pad-markup #0.2 "-48"} dis'2^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }} ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 } - \bar "|" - { b'1^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↓" }} } - \bar "|" - { c''1^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} } - \bar "|" - { f1^\markup { \pad-markup #0.2 "+46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }} ~ } - \bar "|" - { f1 ~ } - \bar "|" - { f1 ~ } - \bar "|" - { f2 gis2^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }} ~ } - \bar "|" - { gis1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/lilypond/part_III.ly deleted file mode 100644 index 370f202..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/lilypond/part_III.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { fis'1^\markup { \pad-markup #0.2 "+11"} ~ } - \bar "|" - { fis'2 gis'2^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }} ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'2 a'2^\markup { \pad-markup #0.2 "+5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↓" }} ~ } - \bar "|" - { a'1 } - \bar "|" - { c''1^\markup { \pad-markup #0.2 "-6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↓" }} } - \bar "|" - { d'1^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↓" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/lilypond/part_IV.ly deleted file mode 100644 index 34d5f50..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4b40ed47/lilypond/part_IV.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { fis'1^\markup { \pad-markup #0.2 "+38"} ~ } - \bar "|" - { fis'1 } - \bar "|" - { g'1^\markup { \pad-markup #0.2 "-35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }} ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'2 g'2^\markup { \pad-markup #0.2 "-26"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }} ~ } - \bar "|" - { g'1 } - \bar "|" - { dis'1^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} } - \bar "|" - { dis'2^\markup { \pad-markup #0.2 "+22"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }} ais'2^\markup { \pad-markup #0.2 "+44"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }} ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'2 b'2^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/4bf1af12_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/4bf1af12_code.scd deleted file mode 100644 index 42b64ff..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/4bf1af12_code.scd +++ /dev/null @@ -1,981 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - /* - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - */ - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - //lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - lastState = if(o == 0, {lastXChanges.last.deepCopy}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - /* - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - */ - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - //# voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - # voices, durs = seq.flatten2(if(oneShot, {2}, {3})).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(2).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/4bf1af12_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/4bf1af12_mus_model.json deleted file mode 100644 index 8d43276..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/4bf1af12_mus_model.json +++ /dev/null @@ -1,87 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -5, 1, 2, 2, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 1, 2, 2, 1, 0 ], [ -3, 0, 2, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 1, 2, 2, 1, 0 ], [ -3, 0, 2, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 1, 2, 2, 1, 0 ], [ -3, 0, 2, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -2, 0, 2, 2, 1, 0 ] ], 1 ], - [ [ [ -4, 0, 2, 2, 1, 0 ], [ -3, 0, 2, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -2, 0, 2, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 0, 2, 2, 1, 0 ], [ -3, 0, 2, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ], - [ [ [ -4, 0, 2, 2, 1, 0 ], [ -3, 0, 2, 2, 1, 0 ], [ -2, 0, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ], - [ [ [ -4, 1, 2, 2, 1, 0 ], [ -3, 0, 2, 2, 1, 0 ], [ -2, 0, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 1, 2, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -2, 0, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ], - [ [ [ -4, 1, 2, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ], - [ [ [ -4, 1, 2, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -3, 1, 3, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 1, 2, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ], [ -3, 1, 3, 2, 1, 0 ] ], 1 ], - [ [ [ -4, 1, 2, 2, 1, 0 ], [ -4, 1, 2, 3, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ], [ -3, 1, 3, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 1, 2, 2, 1, 0 ], [ -4, 1, 2, 3, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -3, 1, 3, 2, 1, 0 ] ], 1 ], - [ [ [ -4, 1, 2, 2, 1, 0 ], [ -4, 1, 2, 3, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -2, 0, 2, 2, 1, 0 ] ], 1 ], - [ [ [ -4, 1, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -2, 0, 2, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 2, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -2, 0, 2, 2, 1, 0 ] ], 1 ], - [ [ [ -4, 2, 2, 2, 1, 0 ], [ -4, 1, 2, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -2, 0, 2, 2, 1, 0 ] ], 1 ], - [ [ [ -4, 2, 2, 2, 1, 0 ], [ -4, 1, 2, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 2, 2, 2, 1, 0 ], [ -4, 1, 2, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ], - [ [ [ -4, 2, 2, 2, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ] - ] - ] -], -"last_changes": -[ - [ [ -4, 2, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -2, 0, 2, 2, 1, 0 ] ], - [ [ -4, 2, 2, 2, 1, 0 ], [ -4, 1, 2, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -2, 0, 2, 2, 1, 0 ] ], - [ [ -4, 2, 2, 2, 1, 0 ], [ -4, 1, 2, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], - [ [ -4, 2, 2, 2, 1, 0 ], [ -4, 1, 2, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], - [ [ -4, 2, 2, 2, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ] -], -"cur_uid": "4bf1af12", -"ref_uid": 44490863, -"order_seed": 556699, -"dur_seed": 515215, -"motifs_seed": 916157, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ 0, 1200, 0.0061728395061728, 0.10227272727273, 0.074074074074074, 0.10227272727273, 0.2037037037037, 0.090909090909091, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.7880658436214, 0.034090909090909, 1, 0.034090909090909 ], -"passages_weights": [ 1, 0.47, 0.43, 1, 0.9 ], -"hd_exp": 9, -"hd_invert": 0, -"order": -[ - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 1 ], [ 3, 2, 0 ], [ ] ], - [ [ 0 ], [ 1, 2, 3 ], [ ] ], - [ [ 3, 0 ], [ 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 2 ], [ 0, 1, 3 ], [ ] ], - [ [ 0, 3 ], [ 2, 1 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 10, 10.091836734694 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/lilypond/part_I.ly deleted file mode 100644 index 28e0f1c..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/lilypond/part_I.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { g'1^\markup { \pad-markup #0.2 "-21"} ~ } - \bar "|" - { g'2 a'2^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { a'2 e'2^\markup { \pad-markup #0.2 "-36"} ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 } - \bar "|" - { g'1^\markup { \pad-markup #0.2 "+50"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { g'1 } - \bar "|" - { a'1^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { a'1 } - \bar "|" - { e'1^\markup { \pad-markup #0.2 "-36"}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/lilypond/part_II.ly deleted file mode 100644 index e6c2955..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/lilypond/part_II.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { b'1^\markup { \pad-markup #0.2 "-34"} } - \bar "|" - { c''1^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { c''1 } - \bar "|" - { a'1^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { a'2 b'2^\markup { \pad-markup #0.2 "-34"} ~ } - \bar "|" - { b'2 e'2^\markup { \pad-markup #0.2 "-36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { e'2 b'2^\markup { \pad-markup #0.2 "-34"} ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'2 c''2^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/lilypond/part_III.ly deleted file mode 100644 index 9111a1e..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/lilypond/part_III.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { g2^\markup { \pad-markup #0.2 "-21"} a2^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a1 } - \bar "|" - { b1^\markup { \pad-markup #0.2 "-34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { b1 } - \bar "|" - { cis'1^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }} ~ } - \bar "|" - { cis'2 e'2^\markup { \pad-markup #0.2 "-36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { e'2 e2^\markup { \pad-markup #0.2 "-36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { e1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/lilypond/part_IV.ly deleted file mode 100644 index 5c0d977..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4bf1af12/lilypond/part_IV.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { e,1^\markup { \pad-markup #0.2 "-36"} ~ } - \bar "|" - { e,1 } - \bar "|" - { a,1^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { a,2 e2^\markup { \pad-markup #0.2 "-36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 } - \bar "|" - { b1^\markup { \pad-markup #0.2 "-34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } - \bar "|" - { b1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4c745666/4c745666_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4c745666/4c745666_code.scd deleted file mode 100644 index 0b55c37..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4c745666/4c745666_code.scd +++ /dev/null @@ -1,977 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - /* - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - */ - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4c745666/4c745666_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4c745666/4c745666_mus_model.json deleted file mode 100644 index 06875fc..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4c745666/4c745666_mus_model.json +++ /dev/null @@ -1,166 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 1 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, -1, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, 1, 0, 0, 0, -1 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, -1, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, 1, 0, 0, 0, -1 ], [ -1, 1, 0, 1, 0, 0 ], [ 0, 1, 0, 0, -1, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 1, 1, 0, 0, 0, -1 ], [ -1, 1, 0, 1, 0, 0 ], [ -1, 2, 0, 1, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 1, 0, 0 ], [ -1, 2, 0, 1, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 1, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 1, 0, 0 ], [ -1, 2, 0, 1, 0, 0 ], [ -1, 1, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ 1, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 1, 0, 0 ], [ -1, 2, 0, 1, 0, 0 ], [ -2, 2, 0, 1, 1, 0 ] ], 1 ], - [ [ [ 1, 0, 0, 0, 0, 0 ], [ -1, 2, 0, 1, -1, 0 ], [ -1, 2, 0, 1, 0, 0 ], [ -2, 2, 0, 1, 1, 0 ] ], 1 ], - [ [ [ -2, 2, 0, 2, 0, 0 ], [ -1, 2, 0, 1, -1, 0 ], [ -1, 2, 0, 1, 0, 0 ], [ -2, 2, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 2, 0, 2, 0, 0 ], [ -1, 2, 0, 1, -1, 0 ], [ -3, 3, 0, 1, 1, 0 ], [ -2, 2, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 2, 0, 2, 0, 0 ], [ -1, 2, 0, 1, -1, 0 ], [ -3, 3, 0, 1, 1, 0 ], [ -1, 2, 0, 1, 0, 0 ] ], 1 ], - [ [ [ -2, 2, 0, 2, 0, 0 ], [ -2, 3, 0, 1, 0, 0 ], [ -3, 3, 0, 1, 1, 0 ], [ -1, 2, 0, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 2, 0, 2, 0, 0 ], [ -2, 3, 0, 1, 0, 0 ], [ -2, 2, 1, 1, 0, 0 ], [ -1, 2, 0, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 2, 0, 1, 0, 0 ], [ -2, 3, 0, 1, 0, 0 ], [ -2, 2, 1, 1, 0, 0 ], [ -1, 2, 0, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 2, 0, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -2, 2, 1, 1, 0, 0 ], [ -1, 2, 0, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 0, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ -1, 2, 0, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 0, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -3, 2, 0, 1, 1, 0 ], [ -1, 2, 0, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 2, 0, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -3, 2, 0, 1, 1, 0 ], [ -1, 2, 0, 1, 0, -1 ] ], 1 ], - [ [ [ -3, 2, 0, 1, 0, 0 ], [ -2, 2, 0, 1, 0, 1 ], [ -3, 2, 0, 1, 1, 0 ], [ -1, 2, 0, 1, 0, -1 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 0, 1, 0, 0 ], [ -1, 2, 0, 1, 1, -1 ], [ -3, 2, 0, 1, 1, 0 ], [ -1, 2, 0, 1, 0, -1 ] ], 1 ], - [ [ [ -3, 2, 0, 1, 0, 0 ], [ -1, 2, 0, 1, 1, -1 ], [ -3, 2, 0, 1, 1, 0 ], [ -1, 2, 0, 0, 1, 0 ] ], 1 ], - [ [ [ -2, 2, 0, 1, 1, -1 ], [ -1, 2, 0, 1, 1, -1 ], [ -3, 2, 0, 1, 1, 0 ], [ -1, 2, 0, 0, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 2, 0, 1, 1, -1 ], [ -1, 2, 0, 1, 1, -1 ], [ -3, 2, 0, 1, 1, 0 ], [ -2, 2, 0, 1, 2, 0 ] ], 1 ], - [ [ [ -2, 2, 0, 1, 1, -1 ], [ -1, 2, 0, 1, 0, 0 ], [ -3, 2, 0, 1, 1, 0 ], [ -2, 2, 0, 1, 2, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 0, 1, 2, 0 ], [ -1, 2, 0, 1, 0, 0 ], [ -3, 2, 0, 1, 1, 0 ], [ -2, 2, 0, 1, 2, 0 ] ], 1 ], - [ [ [ -2, 1, 0, 1, 2, 0 ], [ -1, 2, 0, 1, 0, 0 ], [ -4, 3, 0, 1, 2, 0 ], [ -2, 2, 0, 1, 2, 0 ] ], 1 ], - [ [ [ -2, 1, 0, 1, 2, 0 ], [ -2, 2, 0, 0, 2, 0 ], [ -4, 3, 0, 1, 2, 0 ], [ -2, 2, 0, 1, 2, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 0, 0, 2, 0 ], [ -2, 2, 0, 0, 2, 0 ], [ -4, 3, 0, 1, 2, 0 ], [ -2, 2, 0, 1, 2, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 0, 0, 2, 0 ], [ -2, 3, 0, 0, 2, 0 ], [ -4, 3, 0, 1, 2, 0 ], [ -2, 2, 0, 1, 2, 0 ] ], 1 ], - [ [ [ -3, 3, 0, 0, 2, 0 ], [ -2, 3, 0, 0, 2, 0 ], [ -4, 3, 0, 1, 2, 0 ], [ -2, 2, 0, 1, 2, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 3, 0, 0, 2, 0 ], [ -2, 3, 0, 0, 2, 0 ], [ -4, 3, 0, 1, 2, 0 ], [ -1, 3, 0, 0, 2, -1 ] ], 1 ], - [ [ [ -3, 3, 0, 0, 2, 0 ], [ -2, 3, 1, 0, 2, 0 ], [ -4, 3, 0, 1, 2, 0 ], [ -1, 3, 0, 0, 2, -1 ] ], 1 ], - [ [ [ -3, 3, 0, 0, 2, 0 ], [ -2, 3, 1, 0, 2, 0 ], [ -2, 3, 0, 0, 1, 0 ], [ -1, 3, 0, 0, 2, -1 ] ], 1 ] - ], - [ - [ [ [ -3, 3, 0, 0, 2, 0 ], [ -4, 3, 0, 1, 1, 0 ], [ -2, 3, 0, 0, 1, 0 ], [ -1, 3, 0, 0, 2, -1 ] ], 1 ], - [ [ [ -3, 3, 0, 0, 1, 1 ], [ -4, 3, 0, 1, 1, 0 ], [ -2, 3, 0, 0, 1, 0 ], [ -1, 3, 0, 0, 2, -1 ] ], 1 ] - ], - [ - [ [ [ -3, 3, 0, 0, 1, 1 ], [ -2, 3, 0, 0, 0, 0 ], [ -2, 3, 0, 0, 1, 0 ], [ -1, 3, 0, 0, 2, -1 ] ], 1 ], - [ [ [ -3, 3, 0, 1, 1, 0 ], [ -2, 3, 0, 0, 0, 0 ], [ -2, 3, 0, 0, 1, 0 ], [ -1, 3, 0, 0, 2, -1 ] ], 1 ], - [ [ [ -3, 3, 0, 1, 1, 0 ], [ -2, 3, 0, 0, 0, 0 ], [ -2, 3, 0, 0, 1, 0 ], [ -2, 3, 0, 0, 2, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 3, 0, 1, 0, 0 ], [ -2, 3, 0, 0, 0, 0 ], [ -2, 3, 0, 0, 1, 0 ], [ -2, 3, 0, 0, 2, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 3, 0, 1, 0, 0 ], [ -2, 3, 0, 0, 0, 0 ], [ -2, 3, 0, 0, 1, 0 ], [ -1, 3, 0, 1, 0, -1 ] ], 1 ], - [ [ [ -2, 3, 0, 1, 0, 0 ], [ -2, 3, 0, 0, 0, 0 ], [ -1, 3, 0, 0, 0, 0 ], [ -1, 3, 0, 1, 0, -1 ] ], 1 ], - [ [ [ -2, 3, 0, 1, 0, 0 ], [ -2, 3, 0, 1, -1, 0 ], [ -1, 3, 0, 0, 0, 0 ], [ -1, 3, 0, 1, 0, -1 ] ], 1 ] - ], - [ - [ [ [ -1, 3, -1, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 0 ], [ -1, 3, 0, 0, 0, 0 ], [ -1, 3, 0, 1, 0, -1 ] ], 1 ], - [ [ [ -1, 3, -1, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 1 ], [ -1, 3, 0, 1, 0, -1 ] ], 1 ] - ], - [ - [ [ [ -1, 3, -1, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 1 ], [ -2, 3, 0, 2, -1, 0 ] ], 1 ], - [ [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 1 ], [ -2, 3, 0, 2, -1, 0 ] ], 1 ], - [ [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 0 ], [ -3, 4, 0, 1, -1, 0 ], [ -2, 3, 0, 2, -1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 4, 0, 1, -1, 0 ], [ -3, 4, 0, 1, -1, 0 ], [ -2, 3, 0, 2, -1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 4, 0, 1, -1, 0 ], [ -3, 4, 0, 1, -1, 0 ], [ 0, 3, -1, 0, -1, 0 ] ], 1 ], - [ [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 4, 0, 1, -1, 0 ], [ -2, 3, -1, 1, 0, 0 ], [ 0, 3, -1, 0, -1, 0 ] ], 1 ], - [ [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 4, 0, 1, -1, 0 ], [ "Rest" ], [ 0, 3, -1, 0, -1, 0 ] ], 1 ], - [ [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 4, 0, 1, -1, 0 ], [ "Rest" ], [ "Rest" ] ], 1 ], - [ [ [ -2, 3, -1, 1, -1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, -1, 0, -1, 2 ], [ 0, -1, -1, 1, -1, 2 ], [ 1, 0, -1, 0, -1, 1 ], [ 0, -1, -1, 1, -1, 1 ] ], - [ [ 0, 0, -1, 1, -1, 1 ], [ 0, -1, -1, 1, -1, 2 ], [ 1, 0, -1, 0, -1, 1 ], [ 0, -1, -1, 1, -1, 1 ] ], - [ [ 0, 0, -1, 1, -1, 1 ], [ 0, -1, -1, 1, -1, 2 ], [ 0, -1, -1, 2, -1, 1 ], [ 0, -1, -1, 1, -1, 1 ] ], - [ [ 0, 0, -1, 1, -1, 1 ], [ 1, -1, -1, 0, -1, 1 ], [ 0, -1, -1, 2, -1, 1 ], [ 0, -1, -1, 1, -1, 1 ] ], - [ [ 0, 0, -1, 1, -1, 1 ], [ 1, 0, -1, 0, -1, 1 ], [ 0, -1, -1, 2, -1, 1 ], [ 0, -1, -1, 1, -1, 1 ] ] -], -"cur_uid": "4c745666", -"ref_uid": "nil", -"order_seed": 885120, -"dur_seed": 331456, -"motifs_seed": 712350, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ 0, 1200, 0.0020576131687243, 0.068181818181818, 0.074074074074074, 0.0625, 0.20576131687243, 0.0625, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.78600823045268, 0.068181818181818, 0.98971193415638, 0.0625 ], -"passages_weights": [ 1, 1, 1, 1, 0.1 ], -"hd_exp": 1, -"hd_invert": 0, -"order": -[ - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 2, 3 ], [ 1, 0 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 3, 0 ], [ 1, 2 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 1, 0 ], [ 3, 2 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 0, 3 ], [ 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 2, 1 ], [ 0, 3 ], [ ] ], - [ [ 0 ], [ 1, 2, 3 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 2, 0 ], [ 1, 3 ], [ ] ], - [ [ 1 ], [ 2, 0, 3 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 0, 3 ], [ 2, 1 ], [ ] ], - [ [ 0, 3, 2 ], [ 1 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 24.724489795918, 25 ], -"passages_size": [ 0, 0 ], -"motif_edited": "true", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/4e9f1dcc_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/4e9f1dcc_code.scd deleted file mode 100644 index 42b64ff..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/4e9f1dcc_code.scd +++ /dev/null @@ -1,981 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - /* - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - */ - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - //lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - lastState = if(o == 0, {lastXChanges.last.deepCopy}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - /* - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - */ - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - //# voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - # voices, durs = seq.flatten2(if(oneShot, {2}, {3})).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(2).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/4e9f1dcc_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/4e9f1dcc_mus_model.json deleted file mode 100644 index 38e73bd..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/4e9f1dcc_mus_model.json +++ /dev/null @@ -1,86 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -3, 1, 4, 2, 1, 0 ], [ -4, 1, 5, 2, 1, 1 ], [ -5, 1, 4, 2, 1, 1 ], [ -4, 1, 4, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -6, 1, 4, 2, 1, 2 ], [ -4, 1, 5, 2, 1, 1 ], [ -5, 1, 4, 2, 1, 1 ], [ -4, 1, 4, 2, 1, 0 ] ], 1 ], - [ [ [ -6, 1, 4, 2, 1, 2 ], [ -4, 1, 5, 2, 1, 1 ], [ -5, 1, 4, 2, 1, 1 ], [ -4, 1, 5, 2, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -6, 1, 4, 2, 1, 2 ], [ -4, 1, 4, 2, 0, 1 ], [ -5, 1, 4, 2, 1, 1 ], [ -4, 1, 5, 2, 0, 1 ] ], 1 ], - [ [ [ -6, 1, 4, 2, 1, 2 ], [ -4, 1, 4, 2, 0, 1 ], [ -5, 1, 5, 2, 0, 2 ], [ -4, 1, 5, 2, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -6, 1, 4, 2, 1, 2 ], [ -4, 1, 5, 2, -1, 2 ], [ -5, 1, 5, 2, 0, 2 ], [ -4, 1, 5, 2, 0, 1 ] ], 1 ], - [ [ [ -5, 1, 4, 2, 0, 2 ], [ -4, 1, 5, 2, -1, 2 ], [ -5, 1, 5, 2, 0, 2 ], [ -4, 1, 5, 2, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -4, 0, 5, 2, 0, 1 ], [ -4, 1, 5, 2, -1, 2 ], [ -5, 1, 5, 2, 0, 2 ], [ -4, 1, 5, 2, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -4, 0, 5, 2, 0, 1 ], [ -3, 1, 5, 2, 0, 0 ], [ -5, 1, 5, 2, 0, 2 ], [ -4, 1, 5, 2, 0, 1 ] ], 1 ], - [ [ [ -5, 2, 5, 2, 0, 1 ], [ -3, 1, 5, 2, 0, 0 ], [ -5, 1, 5, 2, 0, 2 ], [ -4, 1, 5, 2, 0, 1 ] ], 1 ] - ], - [ - [ [ [ -5, 2, 5, 2, 0, 1 ], [ -3, 1, 5, 2, 0, 0 ], [ -5, 1, 5, 2, 0, 2 ], [ -4, 1, 5, 2, -1, 2 ] ], 1 ], - [ [ [ -5, 2, 5, 2, 0, 1 ], [ -5, 1, 5, 2, 0, 3 ], [ -5, 1, 5, 2, 0, 2 ], [ -4, 1, 5, 2, -1, 2 ] ], 1 ], - [ [ [ -4, 1, 5, 1, 0, 2 ], [ -5, 1, 5, 2, 0, 3 ], [ -5, 1, 5, 2, 0, 2 ], [ -4, 1, 5, 2, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -4, 1, 5, 1, 0, 2 ], [ -6, 1, 5, 2, 0, 2 ], [ -5, 1, 5, 2, 0, 2 ], [ -4, 1, 5, 2, -1, 2 ] ], 1 ], - [ [ [ -4, 1, 5, 1, 0, 2 ], [ -6, 1, 5, 2, 0, 2 ], [ -5, 1, 5, 2, 0, 2 ], [ -5, 2, 5, 2, 0, 2 ] ], 1 ], - [ [ [ -4, 0, 5, 2, 0, 2 ], [ -6, 1, 5, 2, 0, 2 ], [ -5, 1, 5, 2, 0, 2 ], [ -5, 2, 5, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -4, 0, 5, 2, 0, 2 ], [ -6, 2, 5, 2, 0, 2 ], [ -5, 1, 5, 2, 0, 2 ], [ -5, 2, 5, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -4, 0, 5, 2, 0, 2 ], [ -5, 1, 4, 2, 0, 2 ], [ -5, 1, 5, 2, 0, 2 ], [ -5, 2, 5, 2, 0, 2 ] ], 1 ], - [ [ [ -6, 1, 5, 1, 0, 2 ], [ -5, 1, 4, 2, 0, 2 ], [ -5, 1, 5, 2, 0, 2 ], [ -5, 2, 5, 2, 0, 2 ] ], 1 ], - [ [ [ -6, 1, 5, 1, 0, 2 ], [ -5, 1, 4, 2, 0, 2 ], [ -5, 1, 5, 2, 0, 2 ], [ -5, 1, 5, 2, 0, 3 ] ], 1 ] - ] - ] -], -"last_changes": -[ - [ [ -4, 0, 5, 2, 0, 2 ], [ -6, 1, 5, 2, 0, 2 ], [ -5, 1, 5, 2, 0, 2 ], [ -5, 2, 5, 2, 0, 2 ] ], - [ [ -4, 0, 5, 2, 0, 2 ], [ -6, 2, 5, 2, 0, 2 ], [ -5, 1, 5, 2, 0, 2 ], [ -5, 2, 5, 2, 0, 2 ] ], - [ [ -4, 0, 5, 2, 0, 2 ], [ -5, 1, 4, 2, 0, 2 ], [ -5, 1, 5, 2, 0, 2 ], [ -5, 2, 5, 2, 0, 2 ] ], - [ [ -6, 1, 5, 1, 0, 2 ], [ -5, 1, 4, 2, 0, 2 ], [ -5, 1, 5, 2, 0, 2 ], [ -5, 2, 5, 2, 0, 2 ] ], - [ [ -6, 1, 5, 1, 0, 2 ], [ -5, 1, 4, 2, 0, 2 ], [ -5, 1, 5, 2, 0, 2 ], [ -5, 1, 5, 2, 0, 3 ] ] -], -"cur_uid": "4e9f1dcc", -"ref_uid": "4b40ed47", -"order_seed": 207247, -"dur_seed": 435476, -"motifs_seed": 299289, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ 0, 1200, 0.0061728395061728, 0.10227272727273, 0.074074074074074, 0.10227272727273, 0.2037037037037, 0.090909090909091, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.7880658436214, 0.034090909090909, 1, 0.034090909090909 ], -"passages_weights": [ 1, 0.47, 0.43, 1, 0.3 ], -"hd_exp": 3, -"hd_invert": 0, -"order": -[ - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 1, 2 ], [ 0, 3 ], [ ] ], - [ [ 0, 3 ], [ 1, 2 ], [ ] ], - [ [ 3, 2 ], [ 1, 0 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 2, 3 ], [ 1, 0 ], [ ] ], - [ [ 2 ], [ 3, 1, 0 ], [ ] ], - [ [ 2 ], [ 1, 3, 0 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 10.091836734694, 10.091836734694 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/lilypond/part_I.ly deleted file mode 100644 index bca81dd..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/lilypond/part_I.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { b1^\markup { \pad-markup #0.2 "+36"} } - \bar "|" - { fis'1^\markup { \pad-markup #0.2 "+12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↓" }} ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 } - \bar "|" - { a'1^\markup { \pad-markup #0.2 "+1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↓" }} ~ } - \bar "|" - { a'1 } - \bar "|" - { ais'1^\markup { \pad-markup #0.2 "-46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'2 b'2^\markup { \pad-markup #0.2 "-7"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/lilypond/part_II.ly deleted file mode 100644 index 48f81fd..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/lilypond/part_II.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { gis1^\markup { \pad-markup #0.2 "-23"} ~ } - \bar "|" - { gis1 } - \bar "|" - { dis'1^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }} ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/lilypond/part_III.ly deleted file mode 100644 index 6a243ff..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/lilypond/part_III.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { c''1^\markup { \pad-markup #0.2 "-37"} ~ } - \bar "|" - { c''2 d'2^\markup { \pad-markup #0.2 "+25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↓" }} ~ } - \bar "|" - { d'2 a'2^\markup { \pad-markup #0.2 "+1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↓" }} ~ } - \bar "|" - { a'1 } - \bar "|" - { ais'1^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↓" }} ~ } - \bar "|" - { ais'2 b'2^\markup { \pad-markup #0.2 "-7"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }} ~ } - \bar "|" - { b'2 dis2^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } - \bar "|" - { dis1 } - \bar "|" - { ais2^\markup { \pad-markup #0.2 "-46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} b2^\markup { \pad-markup #0.2 "-34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }} ~ } - \bar "|" - { b1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/lilypond/part_IV.ly deleted file mode 100644 index a370cf4..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4e9f1dcc/lilypond/part_IV.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { b'2^\markup { \pad-markup #0.2 "+36"} e2^\markup { \pad-markup #0.2 "+17"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }} ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 } - \bar "|" - { b2^\markup { \pad-markup #0.2 "-34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }} b2^\markup { \pad-markup #0.2 "+10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }} ~ } - \bar "|" - { b2 cis'2^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }} ~ } - \bar "|" - { cis'1 } - \bar "|" - { f'1^\markup { \pad-markup #0.2 "-17"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }} ~ } - \bar "|" - { f'2 gis'2^\markup { \pad-markup #0.2 "-50"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } - \bar "|" - { gis'1 } - \bar "|" - { f,1^\markup { \pad-markup #0.2 "-17"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/4ef018fc_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/4ef018fc_code.scd deleted file mode 100644 index 57e638d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/4ef018fc_code.scd +++ /dev/null @@ -1,945 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance); -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - noProgIns = (popSize - noSusIns).rand + 1; - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0); - isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/4ef018fc_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/4ef018fc_mus_model.json deleted file mode 100644 index 71a4e25..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/4ef018fc_mus_model.json +++ /dev/null @@ -1,79 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 3.75 ], - [ [ [ 0, 0, 0, 0, 1, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0.75 ] - ], - [ - [ [ [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, -1, 0, 1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0 ], - [ [ [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, -1, 0, 1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 1, 0 ] ], 0.75 ], - [ [ [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, -1, 0, 1, 0 ], [ -1, 0, 0, 0, 1, 0 ], [ 0, -1, 0, 0, 1, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, -1, 0, 1, 0 ], [ -1, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1, -1 ] ], 0.75 ] - ], - [ - [ [ [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, -1, 0, 1, 0 ], [ 0, 0, 0, -1, 1, 0 ], [ 0, 0, 0, 0, 1, -1 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 1, 0 ], [ -1, 1, 0, 0, 1, 0 ], [ 0, 0, 0, -1, 1, 0 ], [ 0, 0, 0, 0, 1, -1 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 1, 0 ], [ -1, 1, 0, 0, 1, 0 ], [ 0, 0, 0, -1, 1, 0 ], [ -1, 0, 0, 0, 2, 0 ] ], 2.5 ] - ], - [ - [ [ [ 0, 0, 0, 0, 1, 0 ], [ "Rest" ], [ 0, 0, 0, -1, 1, 0 ], [ -1, 0, 0, 0, 2, 0 ] ], 0 ], - [ [ [ -1, 0, 0, 0, 2, 1 ], [ "Rest" ], [ 0, 0, 0, -1, 1, 0 ], [ -1, 0, 0, 0, 2, 0 ] ], 0.625 ], - [ [ [ -1, 0, 0, 0, 2, 1 ], [ "Rest" ], [ -2, 0, 0, 1, 2, 0 ], [ -1, 0, 0, 0, 2, 0 ] ], 0 ], - [ [ [ -1, 0, 0, 1, 2, 0 ], [ "Rest" ], [ -2, 0, 0, 1, 2, 0 ], [ -1, 0, 0, 0, 2, 0 ] ], 1.75 ] - ], - [ - [ [ [ -1, 0, 0, 1, 2, 0 ], [ "Rest" ], [ -1, 0, -1, 0, 2, 0 ], [ -1, 0, 0, 0, 2, 0 ] ], 0 ], - [ [ [ 0, 0, 0, 0, 2, 0 ], [ "Rest" ], [ -1, 0, -1, 0, 2, 0 ], [ -1, 0, 0, 0, 2, 0 ] ], 1.125 ], - [ [ [ 0, 0, 0, 0, 2, 0 ], [ -1, 0, 1, 0, 2, 0 ], [ -1, 0, -1, 0, 2, 0 ], [ -1, 0, 0, 0, 2, 0 ] ], 1.125 ], - [ [ [ 0, 0, 0, 0, 2, 0 ], [ -1, 0, 1, 0, 2, 0 ], [ -2, 1, 0, 0, 2, 0 ], [ -1, 0, 0, 0, 2, 0 ] ], 2.625 ] - ], - [ - [ [ [ 0, 0, 0, 0, 2, 0 ], [ -1, 0, 1, 0, 2, 0 ], [ -2, 1, 0, 0, 2, 0 ], [ -2, 2, 0, 0, 2, 0 ] ], 0 ], - [ [ [ -1, 2, 0, 0, 2, 0 ], [ -1, 0, 1, 0, 2, 0 ], [ -2, 1, 0, 0, 2, 0 ], [ -2, 2, 0, 0, 2, 0 ] ], 0 ], - [ [ [ -1, 2, 0, 0, 2, 0 ], [ -2, 1, 0, 1, 2, 0 ], [ -2, 1, 0, 0, 2, 0 ], [ -2, 2, 0, 0, 2, 0 ] ], 0.625 ], - [ [ [ -1, 2, 0, 0, 2, 0 ], [ -1, 1, 0, 0, 2, 0 ], [ -2, 1, 0, 0, 2, 0 ], [ -2, 2, 0, 0, 2, 0 ] ], 2.375 ], - [ [ [ -1, 2, 0, 0, 2, 0 ], [ -1, 1, 0, 0, 2, 0 ], [ -2, 1, 0, 0, 2, 0 ], [ "Rest" ] ], 0 ], - [ [ [ -1, 2, 0, 0, 2, 0 ], [ "Rest" ], [ -2, 1, 0, 0, 2, 0 ], [ "Rest" ] ], 0 ], - [ [ [ "Rest" ], [ "Rest" ], [ -2, 1, 0, 0, 2, 0 ], [ "Rest" ] ], 1.125 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 4.125 ] - ] - ] -], -"last_changes": -[ - [ [ 0, 0, 0, 0, 2, 0 ], [ -1, 0, 1, 0, 2, 0 ], [ -2, 1, 0, 0, 2, 0 ], [ -1, 0, 0, 0, 2, 0 ] ], - [ [ 0, 0, 0, 0, 2, 0 ], [ -1, 0, 1, 0, 2, 0 ], [ -2, 1, 0, 0, 2, 0 ], [ -2, 2, 0, 0, 2, 0 ] ], - [ [ -1, 2, 0, 0, 2, 0 ], [ -1, 0, 1, 0, 2, 0 ], [ -2, 1, 0, 0, 2, 0 ], [ -2, 2, 0, 0, 2, 0 ] ], - [ [ -1, 2, 0, 0, 2, 0 ], [ -2, 1, 0, 1, 2, 0 ], [ -2, 1, 0, 0, 2, 0 ], [ -2, 2, 0, 0, 2, 0 ] ], - [ [ -1, 2, 0, 0, 2, 0 ], [ -1, 1, 0, 0, 2, 0 ], [ -2, 1, 0, 0, 2, 0 ], [ -2, 2, 0, 0, 2, 0 ] ] -], -"cur_uid": "4ef018fc", -"ref_uid": "nil", -"order_seed": 612843, -"dur_seed": 369555, -"motifs_seed": 949457, -"entrances_probs_vals": [ 1, 0, 2.9365079365079, 0.47, 2.8021978021978, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0.48, 0, 2.1031746031746, 0.44, 1.3736263736264, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0.58, 0.95, 4.2063492063492, 0.58, 2.2252747252747, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2021.0526315789, 338 ], [ -1055.1083591331, 1453 ], [ -386, 1675.5417956656 ], [ -219, 1694.1176470588 ] ], -"step_probs_vals": [ -1200, 1200, 0, 0, 0.39094650205761, 0, 0.43621399176955, 0.14772727272727, 0.47942386831276, 0, 0.51440329218107, 0, 0.56378600823045, 0.55113636363636, 0.62139917695473, 0, 1, 0 ], -"passages_weights": [ 0.7, 0.29, 0.66, 0.74, 0.68 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 2 ], [ 0 ], [ 1, 3 ] ], - [ [ 0 ], [ 1, 3, 2, 3 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 3 ], [ 0, 2, 0 ], [ 1 ] ], - [ [ 3 ], [ 2, 0, 1, 2 ], [ ] ], - [ [ 2 ], [ 3, 0, 1, 1 ], [ ] ] -], -"sus_weights": [ 1, 0, 0 ], -"order_size": [ 5.0408163265306, 13.122448979592 ], -"passages_size": [ 0, 2 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/lilypond/part_I.ly deleted file mode 100644 index a915563..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/lilypond/part_I.ly +++ /dev/null @@ -1,26 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r4 ais4^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ ais8[ a8^\markup { \pad-markup #0.2 "+11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ a4 } - \bar "|" - { b1^\markup { \pad-markup #0.2 "+3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }} ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b2. ~ b8[ cis'8^\markup { \pad-markup #0.2 "+7"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }}] ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'4 ~ cis'8[ r8] r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/lilypond/part_II.ly deleted file mode 100644 index a3007ee..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/lilypond/part_II.ly +++ /dev/null @@ -1,26 +0,0 @@ -{ - { c'1^\markup { \pad-markup #0.2 "+0"} ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'2 ~ c'8[ fis8^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ fis4 } - \bar "|" - { gis1^\markup { \pad-markup #0.2 "-18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }} ~ } - \bar "|" - { gis2 ~ gis16[ a8.^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }}] ~ a4 ~ } - \bar "|" - { a4 ~ a8.[ g16^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }}] ~ g2 ~ } - \bar "|" - { g2 ~ g16[ fis8.^\markup { \pad-markup #0.2 "+5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] ~ fis4 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis2. ~ fis8.[ r16] } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/lilypond/part_III.ly deleted file mode 100644 index 69c36d3..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/lilypond/part_III.ly +++ /dev/null @@ -1,26 +0,0 @@ -{ - { r1 } - \bar "|" - { r1 } - \bar "|" - { r4 d'2.^\markup { \pad-markup #0.2 "-35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} } - \bar "|" - { cis'1^\markup { \pad-markup #0.2 "-47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { cis'4 r2. } - \bar "|" - { r1 } - \bar "|" - { dis'1^\markup { \pad-markup #0.2 "-11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { dis'2. ~ dis'8[ e'8^\markup { \pad-markup #0.2 "-27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}] ~ } - \bar "|" - { e'8.[ fis'16^\markup { \pad-markup #0.2 "+5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ fis'2. ~ } - \bar "|" - { fis'4 ~ fis'8[ r8] r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/lilypond/part_IV.ly deleted file mode 100644 index 762d2c4..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/4ef018fc/lilypond/part_IV.ly +++ /dev/null @@ -1,26 +0,0 @@ -{ - { r1 } - \bar "|" - { r2. r8[ fis'8^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↑" }}] ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'4 g'4^\markup { \pad-markup #0.2 "+43"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }} ~ g'16[ a'8.^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ a'4 ~ } - \bar "|" - { a'4 ~ a'8.[ b'16^\markup { \pad-markup #0.2 "+3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ b'2 ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'2. ~ b'8[ cis''8^\markup { \pad-markup #0.2 "+7"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ } - \bar "|" - { cis''1 ~ } - \bar "|" - { cis''4 ~ cis''8[ r8] r2 } - \bar "|" - { r1 } - \bar "|" - { r1 } -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/521654f8_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/521654f8_code.scd deleted file mode 100644 index 42b64ff..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/521654f8_code.scd +++ /dev/null @@ -1,981 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - /* - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - */ - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - //lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - lastState = if(o == 0, {lastXChanges.last.deepCopy}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - /* - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - */ - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - //# voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - # voices, durs = seq.flatten2(if(oneShot, {2}, {3})).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(2).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/521654f8_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/521654f8_mus_model.json deleted file mode 100644 index 6106aa7..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/521654f8_mus_model.json +++ /dev/null @@ -1,87 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -3, 0, 1, 2, 1, 0 ], [ -3, 1, 1, 3, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ -2, 0, 1, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 0, 1, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ -2, 0, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -3, 1, 1, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ -2, 0, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -3, 1, 1, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ -1, 1, 0, 2, 1, -1 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 1, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ -1, 1, 0, 2, 1, -1 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 1, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -3, 2, 1, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -3, 2, 1, 2, 1, 0 ], [ -3, 1, 1, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 1, 2, 1, 0 ], [ -4, 2, 3, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -5, 2, 2, 2, 1, 0 ], [ -4, 2, 3, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -5, 2, 2, 2, 1, 0 ], [ -4, 2, 3, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 3, 2, 2, 1, 0 ], [ -4, 2, 3, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 2, 3, 3, 1, 0 ], [ -4, 2, 3, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ] ], 1 ], - [ [ [ -5, 2, 3, 3, 1, 0 ], [ -4, 2, 3, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -4, 3, 3, 2, 1, 0 ] ], 1 ], - [ [ [ -5, 2, 3, 3, 1, 0 ], [ -4, 2, 3, 2, 1, 0 ], [ -4, 2, 3, 2, 1, 1 ], [ -4, 3, 3, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 2, 3, 3, 1, 0 ], [ -4, 2, 3, 2, 1, 0 ], [ -3, 3, 3, 1, 1, 0 ], [ -4, 3, 3, 2, 1, 0 ] ], 1 ], - [ [ [ -5, 2, 3, 3, 1, 0 ], [ -4, 2, 2, 3, 1, 0 ], [ -3, 3, 3, 1, 1, 0 ], [ -4, 3, 3, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 2, 3, 3, 1, 0 ], [ -4, 2, 2, 3, 1, 0 ], [ -3, 3, 3, 1, 1, 0 ], [ -5, 2, 3, 4, 1, 0 ] ], 1 ], - [ [ [ -5, 2, 3, 3, 1, 0 ], [ -4, 2, 2, 3, 1, 0 ], [ -4, 2, 3, 3, 1, -1 ], [ -5, 2, 3, 4, 1, 0 ] ], 1 ], - [ [ [ -5, 2, 3, 3, 1, 0 ], [ -6, 2, 4, 3, 1, 0 ], [ -4, 2, 3, 3, 1, -1 ], [ -5, 2, 3, 4, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 2, 3, 3, 1, 0 ], [ -6, 2, 4, 3, 1, 0 ], [ -6, 3, 3, 4, 1, 0 ], [ -5, 2, 3, 4, 1, 0 ] ], 1 ] - ] - ] -], -"last_changes": -[ - [ [ -5, 2, 3, 3, 1, 0 ], [ -4, 2, 2, 3, 1, 0 ], [ -3, 3, 3, 1, 1, 0 ], [ -4, 3, 3, 2, 1, 0 ] ], - [ [ -5, 2, 3, 3, 1, 0 ], [ -4, 2, 2, 3, 1, 0 ], [ -3, 3, 3, 1, 1, 0 ], [ -5, 2, 3, 4, 1, 0 ] ], - [ [ -5, 2, 3, 3, 1, 0 ], [ -4, 2, 2, 3, 1, 0 ], [ -4, 2, 3, 3, 1, -1 ], [ -5, 2, 3, 4, 1, 0 ] ], - [ [ -5, 2, 3, 3, 1, 0 ], [ -6, 2, 4, 3, 1, 0 ], [ -4, 2, 3, 3, 1, -1 ], [ -5, 2, 3, 4, 1, 0 ] ], - [ [ -5, 2, 3, 3, 1, 0 ], [ -6, 2, 4, 3, 1, 0 ], [ -6, 3, 3, 4, 1, 0 ], [ -5, 2, 3, 4, 1, 0 ] ] -], -"cur_uid": "521654f8", -"ref_uid": "7ede7adb", -"order_seed": 185690, -"dur_seed": 954582, -"motifs_seed": 356283, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ 0, 1200, 0.0061728395061728, 0.10227272727273, 0.074074074074074, 0.10227272727273, 0.2037037037037, 0.090909090909091, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.7880658436214, 0.034090909090909, 1, 0.034090909090909 ], -"passages_weights": [ 1, 0.47, 0.43, 1, 0.6 ], -"hd_exp": 6, -"hd_invert": 0, -"order": -[ - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 1 ], [ 0, 3, 2 ], [ ] ], - [ [ 0, 3 ], [ 2, 1 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 10.091836734694, 10.091836734694 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/lilypond/part_I.ly deleted file mode 100644 index 4b86b39..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/lilypond/part_I.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { f'1^\markup { \pad-markup #0.2 "-25"} ~ } - \bar "|" - { f'2 c''2^\markup { \pad-markup #0.2 "-50"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↓" }} ~ } - \bar "|" - { c''2 g2^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 } - \bar "|" - { b1^\markup { \pad-markup #0.2 "-34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { b2 ais'2^\markup { \pad-markup #0.2 "-46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'2 ais'2^\markup { \pad-markup #0.2 "-11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }} ~ } - \bar "|" - { ais'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/lilypond/part_II.ly deleted file mode 100644 index 03e091f..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/lilypond/part_II.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { gis'1^\markup { \pad-markup #0.2 "-9"} ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 } - \bar "|" - { b'1^\markup { \pad-markup #0.2 "-34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 } - \bar "|" - { b'2^\markup { \pad-markup #0.2 "-8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }} c''2^\markup { \pad-markup #0.2 "-15"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↓" }} ~ } - \bar "|" - { c''1 } - \bar "|" - { e'1^\markup { \pad-markup #0.2 "-20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/lilypond/part_III.ly deleted file mode 100644 index 8972ef2..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/lilypond/part_III.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { a'2^\markup { \pad-markup #0.2 "+46"} c''2^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''2 c'2^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} } - \bar "|" - { dis'1^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }} ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 } - \bar "|" - { gis'1^\markup { \pad-markup #0.2 "+34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { gis'2 e2^\markup { \pad-markup #0.2 "+7"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/lilypond/part_IV.ly deleted file mode 100644 index 25ed6e8..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/521654f8/lilypond/part_IV.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { f1^\markup { \pad-markup #0.2 "-25"} } - \bar "|" - { c'1^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} } - \bar "|" - { g'1^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'2 b,2^\markup { \pad-markup #0.2 "-34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } - \bar "|" - { b,2 fis2^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }} } - \bar "|" - { c'1^\markup { \pad-markup #0.2 "+21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }} ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/531df78c_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/531df78c_code.scd deleted file mode 100644 index 42b64ff..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/531df78c_code.scd +++ /dev/null @@ -1,981 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - /* - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - */ - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - //lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - lastState = if(o == 0, {lastXChanges.last.deepCopy}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - /* - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - */ - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - //# voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - # voices, durs = seq.flatten2(if(oneShot, {2}, {3})).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(2).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/531df78c_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/531df78c_mus_model.json deleted file mode 100644 index 4f78cc2..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/531df78c_mus_model.json +++ /dev/null @@ -1,157 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -6, 2, 4, 1, 1, 2 ], [ -5, 3, 4, 1, 1, 2 ], [ -6, 3, 4, 1, 1, 2 ], [ -6, 3, 4, 2, 1, 2 ] ], 1 ], - [ [ [ -7, 4, 4, 1, 1, 2 ], [ -5, 3, 4, 1, 1, 2 ], [ -6, 3, 4, 1, 1, 2 ], [ -6, 3, 4, 2, 1, 2 ] ], 1 ], - [ [ [ -7, 4, 4, 1, 1, 2 ], [ -5, 3, 4, 1, 1, 2 ], [ -6, 3, 4, 1, 1, 2 ], [ -5, 2, 4, 1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -5, 3, 4, 0, 1, 2 ], [ -5, 3, 4, 1, 1, 2 ], [ -6, 3, 4, 1, 1, 2 ], [ -5, 2, 4, 1, 1, 2 ] ], 1 ], - [ [ [ -5, 3, 4, 0, 1, 2 ], [ -5, 3, 4, 1, 1, 2 ], [ -6, 3, 4, 1, 1, 2 ], [ -6, 4, 4, 1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -5, 3, 4, 0, 1, 2 ], [ -4, 3, 4, 0, 1, 2 ], [ -6, 3, 4, 1, 1, 2 ], [ -6, 4, 4, 1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -5, 3, 4, 0, 1, 2 ], [ -4, 3, 4, 0, 1, 2 ], [ -6, 3, 4, 1, 1, 2 ], [ -5, 3, 3, 1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -5, 3, 4, 0, 1, 2 ], [ -5, 4, 3, 1, 1, 2 ], [ -6, 3, 4, 1, 1, 2 ], [ -5, 3, 3, 1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 4, 3, 1, 1, 2 ], [ -5, 4, 3, 1, 1, 2 ], [ -6, 3, 4, 1, 1, 2 ], [ -5, 3, 3, 1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -5, 3, 4, 1, 1, 2 ], [ -5, 4, 3, 1, 1, 2 ], [ -6, 3, 4, 1, 1, 2 ], [ -5, 3, 3, 1, 1, 2 ] ], 1 ], - [ [ [ -5, 3, 4, 1, 1, 2 ], [ -6, 3, 3, 1, 1, 2 ], [ -6, 3, 4, 1, 1, 2 ], [ -5, 3, 3, 1, 1, 2 ] ], 1 ], - [ [ [ -5, 3, 4, 1, 1, 2 ], [ -6, 3, 3, 1, 1, 2 ], [ -5, 2, 3, 1, 1, 2 ], [ -5, 3, 3, 1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -5, 3, 4, 1, 1, 2 ], [ -5, 2, 4, 1, 1, 2 ], [ -5, 2, 3, 1, 1, 2 ], [ -5, 3, 3, 1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -5, 3, 4, 1, 1, 2 ], [ -5, 2, 4, 1, 1, 2 ], [ -6, 4, 3, 1, 1, 2 ], [ -5, 3, 3, 1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -5, 3, 4, 1, 1, 2 ], [ -5, 2, 4, 1, 1, 2 ], [ -4, 1, 4, 1, 1, 2 ], [ -5, 3, 3, 1, 1, 2 ] ], 1 ], - [ [ [ -5, 4, 3, 1, 1, 2 ], [ -5, 2, 4, 1, 1, 2 ], [ -4, 1, 4, 1, 1, 2 ], [ -5, 3, 3, 1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -5, 4, 3, 1, 1, 2 ], [ -5, 2, 4, 1, 1, 2 ], [ -4, 2, 3, 1, 1, 2 ], [ -5, 3, 3, 1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -5, 4, 3, 1, 1, 2 ], [ -5, 2, 4, 1, 1, 2 ], [ -4, 2, 3, 1, 1, 2 ], [ -6, 5, 3, 1, 1, 2 ] ], 1 ], - [ [ [ -5, 4, 3, 1, 1, 2 ], [ -5, 4, 3, 0, 1, 2 ], [ -4, 2, 3, 1, 1, 2 ], [ -6, 5, 3, 1, 1, 2 ] ], 1 ], - [ [ [ -5, 4, 3, 1, 1, 2 ], [ -5, 4, 3, 0, 1, 2 ], [ -7, 5, 3, 1, 1, 2 ], [ -6, 5, 3, 1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -5, 4, 3, 1, 1, 2 ], [ -5, 4, 3, 0, 1, 2 ], [ -7, 5, 3, 1, 1, 2 ], [ -5, 5, 3, 0, 1, 2 ] ], 1 ], - [ [ [ -5, 4, 3, 1, 1, 2 ], [ -6, 5, 2, 1, 1, 2 ], [ -7, 5, 3, 1, 1, 2 ], [ -5, 5, 3, 0, 1, 2 ] ], 1 ], - [ [ [ -6, 5, 3, 1, 1, 2 ], [ -6, 5, 2, 1, 1, 2 ], [ -7, 5, 3, 1, 1, 2 ], [ -5, 5, 3, 0, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 5, 3, 1, 1, 2 ], [ -6, 5, 2, 1, 1, 2 ], [ -6, 5, 3, 0, 1, 2 ], [ -5, 5, 3, 0, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 5, 3, 1, 1, 2 ], [ -6, 5, 2, 1, 1, 2 ], [ -6, 5, 3, 0, 1, 2 ], [ -6, 5, 4, 1, 1, 2 ] ], 1 ], - [ [ [ -6, 5, 3, 1, 1, 2 ], [ -6, 6, 3, 0, 1, 2 ], [ -6, 5, 3, 0, 1, 2 ], [ -6, 5, 4, 1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 6, 4, 0, 1, 2 ], [ -6, 6, 3, 0, 1, 2 ], [ -6, 5, 3, 0, 1, 2 ], [ -6, 5, 4, 1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 6, 4, 0, 1, 2 ], [ -6, 6, 3, 0, 1, 2 ], [ -6, 5, 4, 0, 1, 2 ], [ -6, 5, 4, 1, 1, 2 ] ], 1 ], - [ [ [ -6, 6, 4, 0, 1, 2 ], [ -7, 5, 4, 1, 1, 3 ], [ -6, 5, 4, 0, 1, 2 ], [ -6, 5, 4, 1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 5, 4, 0, 1, 3 ], [ -7, 5, 4, 1, 1, 3 ], [ -6, 5, 4, 0, 1, 2 ], [ -6, 5, 4, 1, 1, 2 ] ], 1 ], - [ [ [ -6, 5, 4, 0, 1, 3 ], [ -6, 6, 4, 0, 1, 2 ], [ -6, 5, 4, 0, 1, 2 ], [ -6, 5, 4, 1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 5, 4, 0, 1, 3 ], [ -6, 6, 4, 0, 1, 2 ], [ -6, 5, 4, 0, 1, 2 ], [ -6, 6, 5, 0, 1, 2 ] ], 1 ], - [ [ [ -7, 5, 4, 0, 1, 2 ], [ -6, 6, 4, 0, 1, 2 ], [ -6, 5, 4, 0, 1, 2 ], [ -6, 6, 5, 0, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 5, 4, 0, 1, 2 ], [ -6, 6, 4, 0, 1, 2 ], [ -7, 7, 4, 0, 1, 2 ], [ -6, 6, 5, 0, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 5, 4, 0, 1, 2 ], [ -6, 6, 4, 0, 1, 2 ], [ -7, 7, 4, 0, 1, 2 ], [ -7, 6, 4, 0, 1, 2 ] ], 1 ], - [ [ [ -7, 5, 4, 0, 1, 2 ], [ -6, 6, 4, 0, 1, 2 ], [ -7, 6, 4, 1, 1, 2 ], [ -7, 6, 4, 0, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 5, 4, 0, 1, 2 ], [ -6, 6, 4, 0, 1, 2 ], [ -5, 6, 4, -1, 1, 2 ], [ -7, 6, 4, 0, 1, 2 ] ], 1 ], - [ [ [ -8, 7, 4, 0, 1, 2 ], [ -6, 6, 4, 0, 1, 2 ], [ -5, 6, 4, -1, 1, 2 ], [ -7, 6, 4, 0, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -8, 7, 4, 0, 1, 2 ], [ -6, 6, 4, 0, 1, 2 ], [ -5, 6, 4, -1, 1, 2 ], [ -6, 7, 4, -1, 1, 2 ] ], 1 ], - [ [ [ -7, 7, 4, -1, 1, 2 ], [ -6, 6, 4, 0, 1, 2 ], [ -5, 6, 4, -1, 1, 2 ], [ -6, 7, 4, -1, 1, 2 ] ], 1 ], - [ [ [ -7, 7, 4, -1, 1, 2 ], [ -6, 6, 4, -1, 1, 2 ], [ -5, 6, 4, -1, 1, 2 ], [ -6, 7, 4, -1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 6, 4, -1, 1, 2 ], [ -6, 6, 4, -1, 1, 2 ], [ -5, 6, 4, -1, 1, 2 ], [ -6, 7, 4, -1, 1, 2 ] ], 1 ], - [ [ [ -7, 6, 4, -1, 1, 2 ], [ -5, 6, 4, -1, 0, 2 ], [ -5, 6, 4, -1, 1, 2 ], [ -6, 7, 4, -1, 1, 2 ] ], 1 ], - [ [ [ -7, 6, 4, -1, 1, 2 ], [ -5, 6, 4, -1, 0, 2 ], [ -5, 6, 4, -1, 1, 2 ], [ -6, 6, 4, 0, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 6, 4, -1, 1, 2 ], [ -5, 6, 4, -1, 0, 2 ], [ -6, 6, 4, 0, 0, 2 ], [ -6, 6, 4, 0, 1, 2 ] ], 1 ], - [ [ [ -7, 6, 4, -1, 1, 2 ], [ -6, 6, 5, 0, 1, 2 ], [ -6, 6, 4, 0, 0, 2 ], [ -6, 6, 4, 0, 1, 2 ] ], 1 ] - ] - ] -], -"last_changes": -[ - [ [ -7, 6, 4, -1, 1, 2 ], [ -6, 6, 4, -1, 1, 2 ], [ -5, 6, 4, -1, 1, 2 ], [ -6, 7, 4, -1, 1, 2 ] ], - [ [ -7, 6, 4, -1, 1, 2 ], [ -5, 6, 4, -1, 0, 2 ], [ -5, 6, 4, -1, 1, 2 ], [ -6, 7, 4, -1, 1, 2 ] ], - [ [ -7, 6, 4, -1, 1, 2 ], [ -5, 6, 4, -1, 0, 2 ], [ -5, 6, 4, -1, 1, 2 ], [ -6, 6, 4, 0, 1, 2 ] ], - [ [ -7, 6, 4, -1, 1, 2 ], [ -5, 6, 4, -1, 0, 2 ], [ -6, 6, 4, 0, 0, 2 ], [ -6, 6, 4, 0, 1, 2 ] ], - [ [ -7, 6, 4, -1, 1, 2 ], [ -6, 6, 5, 0, 1, 2 ], [ -6, 6, 4, 0, 0, 2 ], [ -6, 6, 4, 0, 1, 2 ] ] -], -"cur_uid": "531df78c", -"ref_uid": "78a94ed1", -"order_seed": 561112, -"dur_seed": 221568, -"motifs_seed": 960151, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ 0, 1200, 0.0061728395061728, 0.10227272727273, 0.074074074074074, 0.10227272727273, 0.2037037037037, 0.090909090909091, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.7880658436214, 0.034090909090909, 1, 0.034090909090909 ], -"passages_weights": [ 0.08, 0.47, 0.43, 1, 1 ], -"hd_exp": 10, -"hd_invert": 0, -"order": -[ - [ [ 1 ], [ 2, 0, 3 ], [ ] ], - [ [ 2, 1 ], [ 0, 3 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 1, 3, 2 ], [ 0 ], [ ] ], - [ [ 3 ], [ 0, 1, 2 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 3, 1 ], [ 2, 0 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 2 ], [ 3, 1, 0 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 0, 2 ], [ 3, 1 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 3, 0 ], [ 2, 1 ], [ ] ], - [ [ 3, 2 ], [ 0, 1 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 0, 1 ], [ 3, 2 ], [ ] ], - [ [ 3, 1 ], [ 2, 0 ], [ ] ], - [ [ 2 ], [ 3, 0, 1 ], [ ] ], - [ [ 2 ], [ 0, 1, 3 ], [ ] ], - [ [ 3, 0 ], [ 2, 1 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 25, 25.244897959184 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/lilypond/part_I.ly deleted file mode 100644 index 0acee0f..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/lilypond/part_I.ly +++ /dev/null @@ -1,48 +0,0 @@ -{ - { fis'1^\markup { \pad-markup #0.2 "+21"} } - \bar "|" - { d'1^\markup { \pad-markup #0.2 "-50"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} } - \bar "|" - { e'1^\markup { \pad-markup #0.2 "-46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} } - \bar "|" - { f'1^\markup { \pad-markup #0.2 "-34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }} ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'2 g'2^\markup { \pad-markup #0.2 "-30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { g'1 } - \bar "|" - { a'1^\markup { \pad-markup #0.2 "+1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { a'1 } - \bar "|" - { b'1^\markup { \pad-markup #0.2 "-44"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'2 c''2^\markup { \pad-markup #0.2 "-24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }} ~ } - \bar "|" - { c''1 } - \bar "|" - { gis1^\markup { \pad-markup #0.2 "-11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { gis1 } - \bar "|" - { f'1^\markup { \pad-markup #0.2 "+22"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }} ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'2 gis'2^\markup { \pad-markup #0.2 "-11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }} ~ } - \bar "|" - { gis'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/lilypond/part_II.ly deleted file mode 100644 index 71926a1..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/lilypond/part_II.ly +++ /dev/null @@ -1,48 +0,0 @@ -{ - { a1^\markup { \pad-markup #0.2 "-48"} ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a2 ais2^\markup { \pad-markup #0.2 "-36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } - \bar "|" - { ais2 c'2^\markup { \pad-markup #0.2 "-32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }} } - \bar "|" - { fis'1^\markup { \pad-markup #0.2 "+48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} } - \bar "|" - { ais'1^\markup { \pad-markup #0.2 "-36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }} ~ } - \bar "|" - { ais'2 g2^\markup { \pad-markup #0.2 "-30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g2 a2^\markup { \pad-markup #0.2 "+1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a2 cis'2^\markup { \pad-markup #0.2 "-13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'2 dis'2^\markup { \pad-markup #0.2 "-9"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { dis'2 fis'2^\markup { \pad-markup #0.2 "-42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }} } - \bar "|" - { ais'1^\markup { \pad-markup #0.2 "+21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }} ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 } - \bar "|" - { d'1^\markup { \pad-markup #0.2 "+38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/lilypond/part_III.ly deleted file mode 100644 index 95b2a0b..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/lilypond/part_III.ly +++ /dev/null @@ -1,48 +0,0 @@ -{ - { a'1^\markup { \pad-markup #0.2 "-48"} ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'2 b'2^\markup { \pad-markup #0.2 "-17"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { b'2 c''2^\markup { \pad-markup #0.2 "-32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }} ~ } - \bar "|" - { c''1 } - \bar "|" - { f1^\markup { \pad-markup #0.2 "-34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} } - \bar "|" - { d'1^\markup { \pad-markup #0.2 "-50"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'1 } - \bar "|" - { d'1^\markup { \pad-markup #0.2 "-1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }} ~ } - \bar "|" - { d'2 dis'2^\markup { \pad-markup #0.2 "-16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }} ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'2 e'2^\markup { \pad-markup #0.2 "+3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }} ~ } - \bar "|" - { e'1 } - \bar "|" - { g'1^\markup { \pad-markup #0.2 "-3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }} } - \bar "|" - { gis'1^\markup { \pad-markup #0.2 "-11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }} ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 } - \bar "|" - { ais1^\markup { \pad-markup #0.2 "+21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} } - \bar "|" - { f'1^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }} ~ } - \bar "|" - { f'2 c''2^\markup { \pad-markup #0.2 "-24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/lilypond/part_IV.ly deleted file mode 100644 index 52220bd..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/531df78c/lilypond/part_IV.ly +++ /dev/null @@ -1,48 +0,0 @@ -{ - { d2^\markup { \pad-markup #0.2 "-50"} e2^\markup { \pad-markup #0.2 "-46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { e2 b2^\markup { \pad-markup #0.2 "-17"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }} ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 } - \bar "|" - { c'2^\markup { \pad-markup #0.2 "-32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} a'2^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'2 c''2^\markup { \pad-markup #0.2 "-32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }} ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''1 } - \bar "|" - { g'1^\markup { \pad-markup #0.2 "-30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } - \bar "|" - { g'1 } - \bar "|" - { gis'1^\markup { \pad-markup #0.2 "-11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }} ~ } - \bar "|" - { gis'2 a'2^\markup { \pad-markup #0.2 "+28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }} ~ } - \bar "|" - { a'1 } - \bar "|" - { cis1^\markup { \pad-markup #0.2 "-13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } - \bar "|" - { cis1 ~ } - \bar "|" - { cis2 dis2^\markup { \pad-markup #0.2 "-9"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { dis2 f2^\markup { \pad-markup #0.2 "+22"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { f2 ais,2^\markup { \pad-markup #0.2 "+21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { ais,1 ~ } - \bar "|" - { ais,1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/553fbac7/553fbac7_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/553fbac7/553fbac7_code.scd deleted file mode 100644 index c4e3d1b..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/553fbac7/553fbac7_code.scd +++ /dev/null @@ -1,979 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - /* - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - */ - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - /* - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - */ - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/553fbac7/553fbac7_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/553fbac7/553fbac7_mus_model.json deleted file mode 100644 index da17f28..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/553fbac7/553fbac7_mus_model.json +++ /dev/null @@ -1,88 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ "Rest" ], [ 0, 1, 0, 0, 0, 0 ], [ "Rest" ] ], 1 ], - [ [ [ 0, 1, 1, 0, 0, 0 ], [ "Rest" ], [ 0, 1, 0, 0, 0, 0 ], [ "Rest" ] ], 1 ], - [ [ [ 0, 1, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ "Rest" ] ], 1 ], - [ [ [ 0, 1, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 1, 0, 0, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ -1, 2, 0, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ] ], 1 ], - [ [ [ -2, 1, 0, 0, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 0, 0, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 0, 0, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 2, 1, -1, -1, -1, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 1 ], - [ [ [ -2, 1, 0, 0, 0, 0 ], [ 1, 1, -1, -1, -1, 0 ], [ 2, 1, -1, -1, -1, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 1 ], - [ [ [ 0, 1, -1, -1, -1, 0 ], [ 1, 1, -1, -1, -1, 0 ], [ 2, 1, -1, -1, -1, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 1 ] - ] - ] -], -"last_changes": -[ - [ [ -2, 1, 0, 0, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ] ], - [ [ -2, 1, 0, 0, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 0, 1, 1, 0, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], - [ [ -2, 1, 0, 0, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 2, 1, -1, -1, -1, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], - [ [ -2, 1, 0, 0, 0, 0 ], [ 1, 1, -1, -1, -1, 0 ], [ 2, 1, -1, -1, -1, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], - [ [ 0, 1, -1, -1, -1, 0 ], [ 1, 1, -1, -1, -1, 0 ], [ 2, 1, -1, -1, -1, 0 ], [ 1, 1, -1, -1, 0, 0 ] ] -], -"cur_uid": "553fbac7", -"ref_uid": "4874dd07", -"order_seed": 846356, -"dur_seed": 787877, -"motifs_seed": 285247, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ 0, 1200, 0.0061728395061728, 0.10227272727273, 0.074074074074074, 0.10227272727273, 0.2037037037037, 0.090909090909091, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.7880658436214, 0.034090909090909, 1, 0.034090909090909 ], -"passages_weights": [ 1, 0.47, 0.43, 1, 0.9 ], -"hd_exp": 9, -"hd_invert": 0, -"order": -[ - [ [ 2 ], [ 0, 1, 3 ], [ ] ], - [ [ 1 ], [ 0, 3, 2 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 3 ], [ 1, 2, 0 ], [ ] ], - [ [ 0, 3 ], [ 2, 1 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 10.061224489796, 10.091836734694 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/57ef90e6/57ef90e6_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/57ef90e6/57ef90e6_code.scd deleted file mode 100644 index 0d8c24b..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/57ef90e6/57ef90e6_code.scd +++ /dev/null @@ -1,975 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(mSeq.maxDepth - 5).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/57ef90e6/57ef90e6_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/57ef90e6/57ef90e6_mus_model.json deleted file mode 100644 index 0f2fec3..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/57ef90e6/57ef90e6_mus_model.json +++ /dev/null @@ -1,166 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 1 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1 ], - [ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, -1, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, 1, 0, 0, 0, -1 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, -1, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, 1, 0, 0, 0, -1 ], [ -1, 1, 0, 1, 0, 0 ], [ 0, 1, 0, 0, -1, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 1, 1, 0, 0, 0, -1 ], [ -1, 1, 0, 1, 0, 0 ], [ -1, 2, 0, 1, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 1, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 1, 0, 0 ], [ -1, 2, 0, 1, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 1, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 1, 0, 0 ], [ -1, 2, 0, 1, 0, 0 ], [ -1, 1, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ 1, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 1, 0, 0 ], [ -1, 2, 0, 1, 0, 0 ], [ -2, 2, 0, 1, 1, 0 ] ], 1 ], - [ [ [ 1, 0, 0, 0, 0, 0 ], [ -1, 2, 0, 1, -1, 0 ], [ -1, 2, 0, 1, 0, 0 ], [ -2, 2, 0, 1, 1, 0 ] ], 1 ], - [ [ [ -2, 2, 0, 2, 0, 0 ], [ -1, 2, 0, 1, -1, 0 ], [ -1, 2, 0, 1, 0, 0 ], [ -2, 2, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 2, 0, 2, 0, 0 ], [ -1, 2, 0, 1, -1, 0 ], [ -3, 3, 0, 1, 1, 0 ], [ -2, 2, 0, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 2, 0, 2, 0, 0 ], [ -1, 2, 0, 1, -1, 0 ], [ -3, 3, 0, 1, 1, 0 ], [ -1, 2, 0, 1, 0, 0 ] ], 1 ], - [ [ [ -2, 2, 0, 2, 0, 0 ], [ -2, 3, 0, 1, 0, 0 ], [ -3, 3, 0, 1, 1, 0 ], [ -1, 2, 0, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 2, 0, 2, 0, 0 ], [ -2, 3, 0, 1, 0, 0 ], [ -2, 2, 1, 1, 0, 0 ], [ -1, 2, 0, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 2, 0, 1, 0, 0 ], [ -2, 3, 0, 1, 0, 0 ], [ -2, 2, 1, 1, 0, 0 ], [ -1, 2, 0, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 2, 0, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -2, 2, 1, 1, 0, 0 ], [ -1, 2, 0, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 0, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ 0, 2, -1, 0, 0, 0 ], [ -1, 2, 0, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 0, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -3, 2, 0, 1, 1, 0 ], [ -1, 2, 0, 1, 0, 0 ] ], 1 ], - [ [ [ -3, 2, 0, 1, 0, 0 ], [ -1, 2, -1, 1, 0, 0 ], [ -3, 2, 0, 1, 1, 0 ], [ -1, 2, 0, 1, 0, -1 ] ], 1 ], - [ [ [ -3, 2, 0, 1, 0, 0 ], [ -2, 2, 0, 1, 0, 1 ], [ -3, 2, 0, 1, 1, 0 ], [ -1, 2, 0, 1, 0, -1 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 0, 1, 0, 0 ], [ -1, 2, 0, 1, 1, -1 ], [ -3, 2, 0, 1, 1, 0 ], [ -1, 2, 0, 1, 0, -1 ] ], 1 ], - [ [ [ -3, 2, 0, 1, 0, 0 ], [ -1, 2, 0, 1, 1, -1 ], [ -3, 2, 0, 1, 1, 0 ], [ -1, 2, 0, 0, 1, 0 ] ], 1 ], - [ [ [ -2, 2, 0, 1, 1, -1 ], [ -1, 2, 0, 1, 1, -1 ], [ -3, 2, 0, 1, 1, 0 ], [ -1, 2, 0, 0, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 2, 0, 1, 1, -1 ], [ -1, 2, 0, 1, 1, -1 ], [ -3, 2, 0, 1, 1, 0 ], [ -2, 2, 0, 1, 2, 0 ] ], 1 ], - [ [ [ -2, 2, 0, 1, 1, -1 ], [ -1, 2, 0, 1, 0, 0 ], [ -3, 2, 0, 1, 1, 0 ], [ -2, 2, 0, 1, 2, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 0, 1, 2, 0 ], [ -1, 2, 0, 1, 0, 0 ], [ -3, 2, 0, 1, 1, 0 ], [ -2, 2, 0, 1, 2, 0 ] ], 1 ], - [ [ [ -2, 1, 0, 1, 2, 0 ], [ -1, 2, 0, 1, 0, 0 ], [ -4, 3, 0, 1, 2, 0 ], [ -2, 2, 0, 1, 2, 0 ] ], 1 ], - [ [ [ -2, 1, 0, 1, 2, 0 ], [ -2, 2, 0, 0, 2, 0 ], [ -4, 3, 0, 1, 2, 0 ], [ -2, 2, 0, 1, 2, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 0, 0, 2, 0 ], [ -2, 2, 0, 0, 2, 0 ], [ -4, 3, 0, 1, 2, 0 ], [ -2, 2, 0, 1, 2, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 0, 0, 2, 0 ], [ -2, 3, 0, 0, 2, 0 ], [ -4, 3, 0, 1, 2, 0 ], [ -2, 2, 0, 1, 2, 0 ] ], 1 ], - [ [ [ -3, 3, 0, 0, 2, 0 ], [ -2, 3, 0, 0, 2, 0 ], [ -4, 3, 0, 1, 2, 0 ], [ -2, 2, 0, 1, 2, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 3, 0, 0, 2, 0 ], [ -2, 3, 0, 0, 2, 0 ], [ -4, 3, 0, 1, 2, 0 ], [ -1, 3, 0, 0, 2, -1 ] ], 1 ], - [ [ [ -3, 3, 0, 0, 2, 0 ], [ -2, 3, 1, 0, 2, 0 ], [ -4, 3, 0, 1, 2, 0 ], [ -1, 3, 0, 0, 2, -1 ] ], 1 ], - [ [ [ -3, 3, 0, 0, 2, 0 ], [ -2, 3, 1, 0, 2, 0 ], [ -2, 3, 0, 0, 1, 0 ], [ -1, 3, 0, 0, 2, -1 ] ], 1 ] - ], - [ - [ [ [ -3, 3, 0, 0, 2, 0 ], [ -4, 3, 0, 1, 1, 0 ], [ -2, 3, 0, 0, 1, 0 ], [ -1, 3, 0, 0, 2, -1 ] ], 1 ], - [ [ [ -3, 3, 0, 0, 1, 1 ], [ -4, 3, 0, 1, 1, 0 ], [ -2, 3, 0, 0, 1, 0 ], [ -1, 3, 0, 0, 2, -1 ] ], 1 ] - ], - [ - [ [ [ -3, 3, 0, 0, 1, 1 ], [ -2, 3, 0, 0, 0, 0 ], [ -2, 3, 0, 0, 1, 0 ], [ -1, 3, 0, 0, 2, -1 ] ], 1 ], - [ [ [ -3, 3, 0, 1, 1, 0 ], [ -2, 3, 0, 0, 0, 0 ], [ -2, 3, 0, 0, 1, 0 ], [ -1, 3, 0, 0, 2, -1 ] ], 1 ], - [ [ [ -3, 3, 0, 1, 1, 0 ], [ -2, 3, 0, 0, 0, 0 ], [ -2, 3, 0, 0, 1, 0 ], [ -2, 3, 0, 0, 2, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 3, 0, 1, 0, 0 ], [ -2, 3, 0, 0, 0, 0 ], [ -2, 3, 0, 0, 1, 0 ], [ -2, 3, 0, 0, 2, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 3, 0, 1, 0, 0 ], [ -2, 3, 0, 0, 0, 0 ], [ -2, 3, 0, 0, 1, 0 ], [ -1, 3, 0, 1, 0, -1 ] ], 1 ], - [ [ [ -2, 3, 0, 1, 0, 0 ], [ -2, 3, 0, 0, 0, 0 ], [ -1, 3, 0, 0, 0, 0 ], [ -1, 3, 0, 1, 0, -1 ] ], 1 ], - [ [ [ -2, 3, 0, 1, 0, 0 ], [ -2, 3, 0, 1, -1, 0 ], [ -1, 3, 0, 0, 0, 0 ], [ -1, 3, 0, 1, 0, -1 ] ], 1 ] - ], - [ - [ [ [ -1, 3, -1, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 0 ], [ -1, 3, 0, 0, 0, 0 ], [ -1, 3, 0, 1, 0, -1 ] ], 1 ], - [ [ [ -1, 3, -1, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 1 ], [ -1, 3, 0, 1, 0, -1 ] ], 1 ] - ], - [ - [ [ [ -1, 3, -1, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 1 ], [ -2, 3, 0, 2, -1, 0 ] ], 1 ], - [ [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 1 ], [ -2, 3, 0, 2, -1, 0 ] ], 1 ], - [ [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 0 ], [ -3, 4, 0, 1, -1, 0 ], [ -2, 3, 0, 2, -1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 4, 0, 1, -1, 0 ], [ -3, 4, 0, 1, -1, 0 ], [ -2, 3, 0, 2, -1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 4, 0, 1, -1, 0 ], [ -3, 4, 0, 1, -1, 0 ], [ 0, 3, -1, 0, -1, 0 ] ], 1 ], - [ [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 4, 0, 1, -1, 0 ], [ -2, 3, -1, 1, 0, 0 ], [ 0, 3, -1, 0, -1, 0 ] ], 1 ], - [ [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 4, 0, 1, -1, 0 ], [ "Rest" ], [ 0, 3, -1, 0, -1, 0 ] ], 1 ], - [ [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 4, 0, 1, -1, 0 ], [ "Rest" ], [ "Rest" ] ], 1 ], - [ [ [ -2, 3, -1, 1, -1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1 ], - [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3 ] - ] - ] -], -"last_changes": -[ - [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 1 ], [ -2, 3, 0, 2, -1, 0 ] ], - [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 3, 0, 1, -1, 0 ], [ -3, 4, 0, 1, -1, 0 ], [ -2, 3, 0, 2, -1, 0 ] ], - [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 4, 0, 1, -1, 0 ], [ -3, 4, 0, 1, -1, 0 ], [ -2, 3, 0, 2, -1, 0 ] ], - [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 4, 0, 1, -1, 0 ], [ -3, 4, 0, 1, -1, 0 ], [ 0, 3, -1, 0, -1, 0 ] ], - [ [ -2, 3, -1, 1, -1, 0 ], [ -2, 4, 0, 1, -1, 0 ], [ -2, 3, -1, 1, 0, 0 ], [ 0, 3, -1, 0, -1, 0 ] ] -], -"cur_uid": "57ef90e6", -"ref_uid": "nil", -"order_seed": 486941, -"dur_seed": 852979, -"motifs_seed": 409375, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ 0, 1200, 0.0020576131687243, 0.068181818181818, 0.074074074074074, 0.0625, 0.20576131687243, 0.0625, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.78600823045268, 0.068181818181818, 0.98971193415638, 0.0625 ], -"passages_weights": [ 1, 1, 1, 1, 0.1 ], -"hd_exp": 1, -"hd_invert": 0, -"order": -[ - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 3 ], [ 2, 0, 1 ], [ ] ], - [ [ 1, 3 ], [ 2, 0 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 2 ], [ 3, 1, 0 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 2, 0 ], [ 3, 1 ], [ ] ], - [ [ 3 ], [ 2, 0, 1 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 2 ], [ 1, 3, 0 ], [ ] ], - [ [ 2, 0 ], [ 3, 1 ], [ ] ], - [ [ 3 ], [ 0, 2, 1 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 2, 3 ], [ 1, 0 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 2, 3 ], [ 1, 0 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 1, 3 ], [ 0, 2 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 0, 1 ], [ 3, 2 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 24.896551724138, 24.896551724138 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/615c4008/615c4008_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/615c4008/615c4008_code.scd deleted file mode 100644 index 070e09d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/615c4008/615c4008_code.scd +++ /dev/null @@ -1,992 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - //[chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - //[minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - /* - noSilentIns = (popSize - noSusIns).rand.clip(0, 1); - noProgIns = popSize - noSusIns - noSilentIns; - */ - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - //prog = ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}); - - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - //candidates.select({arg item; (item ++ voices).asSet.size >= 4}); - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - //recentlySoundedScore = inclusionScore.value(lastXChanges.flatten.collect({arg item; item.drop(1)}), candidate.drop(1), 0.01); - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}).postln; - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - nProbs.round(0.001).postln; - [candidates, nProbs.round(0.001)].flop.postln; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - /* - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - */ - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - //lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - lastState = if(o == 0, {lastXChanges.last.deepCopy}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - /* - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - */ - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - //# voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - # voices, durs = seq.flatten2(if(oneShot, {2}, {3})).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(2).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/615c4008/615c4008_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/615c4008/615c4008_mus_model.json deleted file mode 100644 index 65a90eb..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/615c4008/615c4008_mus_model.json +++ /dev/null @@ -1,267 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -9, 5, 1, 4, -1, 2 ], [ -8, 5, 2, 4, -2, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 1, 4, -2, 2 ] ], 0.25 ], - [ [ [ -9, 6, 1, 4, -2, 2 ], [ -8, 5, 2, 4, -2, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 1, 4, -2, 2 ] ], 0 ], - [ [ [ -9, 6, 1, 4, -2, 2 ], [ -8, 5, 2, 4, -2, 2 ], [ -7, 6, 1, 4, -2, 2 ], [ -6, 5, 1, 4, -2, 2 ] ], 0 ], - [ [ [ -9, 6, 1, 4, -2, 2 ], [ -7, 4, 1, 4, -2, 2 ], [ -7, 6, 1, 4, -2, 2 ], [ -6, 5, 1, 4, -2, 2 ] ], 0.25 ], - [ [ [ -9, 6, 1, 4, -2, 2 ], [ -8, 6, 1, 4, -2, 2 ], [ -7, 6, 1, 4, -2, 2 ], [ -6, 5, 1, 4, -2, 2 ] ], 0.25 ], - [ [ [ -9, 6, 1, 4, -2, 2 ], [ -7, 5, 1, 4, -2, 2 ], [ -7, 6, 1, 4, -2, 2 ], [ -6, 5, 1, 4, -2, 2 ] ], 0.25 ] - ], - [ - [ [ [ -9, 6, 1, 4, -2, 2 ], [ -8, 7, 1, 4, -2, 2 ], [ -7, 6, 1, 4, -2, 2 ], [ -6, 5, 1, 4, -2, 2 ] ], 0 ], - [ [ [ -9, 6, 1, 4, -2, 2 ], [ -8, 7, 1, 4, -2, 2 ], [ -7, 6, 1, 4, -2, 2 ], [ -7, 7, 1, 4, -2, 2 ] ], 0 ], - [ [ [ -9, 7, 1, 4, -2, 2 ], [ -8, 7, 1, 4, -2, 2 ], [ -7, 6, 1, 4, -2, 2 ], [ -7, 7, 1, 4, -2, 2 ] ], 0.25 ], - [ [ [ -9, 7, 1, 4, -2, 2 ], [ -7, 6, 0, 4, -2, 2 ], [ -7, 6, 1, 4, -2, 2 ], [ -7, 7, 1, 4, -2, 2 ] ], 0.25 ] - ], - [ - [ [ [ -9, 7, 1, 4, -2, 2 ], [ -7, 6, 0, 4, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -7, 7, 1, 4, -2, 2 ] ], 0 ], - [ [ [ -9, 7, 1, 4, -2, 2 ], [ -7, 6, 0, 4, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -6, 6, 0, 4, -2, 2 ] ], 0.25 ], - [ [ [ -8, 6, 0, 4, -2, 2 ], [ -7, 6, 0, 4, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -6, 6, 0, 4, -2, 2 ] ], 0.25 ] - ], - [ - [ [ [ -8, 6, 0, 4, -2, 2 ], [ -7, 7, 0, 4, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -6, 6, 0, 4, -2, 2 ] ], 0.25 ], - [ [ [ -9, 7, 0, 4, -2, 2 ], [ -7, 7, 0, 4, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -6, 6, 0, 4, -2, 2 ] ], 0.25 ], - [ [ [ -9, 7, 0, 4, -2, 2 ], [ -7, 7, 0, 4, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -8, 8, 0, 4, -2, 2 ] ], 0 ], - [ [ [ -8, 7, 0, 3, -2, 2 ], [ -7, 7, 0, 4, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -8, 8, 0, 4, -2, 2 ] ], 0 ], - [ [ [ -8, 7, 0, 3, -2, 2 ], [ -6, 7, 0, 3, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -8, 8, 0, 4, -2, 2 ] ], 0.25 ], - [ [ [ -8, 7, 0, 3, -2, 2 ], [ -6, 7, 0, 3, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -7, 7, 0, 3, -2, 2 ] ], 0 ], - [ [ [ -8, 7, 0, 3, -2, 2 ], [ -7, 7, 1, 4, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -7, 7, 0, 3, -2, 2 ] ], 0.25 ] - ], - [ - [ [ [ -8, 7, 0, 3, -2, 2 ], [ -7, 7, 1, 4, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -7, 7, 0, 4, -2, 2 ] ], 0.25 ], - [ [ [ -8, 7, 0, 3, -2, 2 ], [ -7, 6, 0, 4, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -7, 7, 0, 4, -2, 2 ] ], 0.25 ], - [ [ [ -8, 7, 0, 3, -2, 2 ], [ -8, 8, 0, 4, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -7, 7, 0, 4, -2, 2 ] ], 0 ], - [ [ [ -8, 7, 0, 3, -2, 2 ], [ -8, 8, 0, 4, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -6, 7, 0, 3, -2, 2 ] ], 0.25 ], - [ [ [ -8, 7, 0, 3, -2, 2 ], [ -8, 8, 0, 4, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -7, 7, 1, 4, -2, 2 ] ], 0.25 ], - [ [ [ -8, 7, 0, 3, -2, 2 ], [ -8, 8, 0, 4, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -6, 6, 0, 4, -2, 2 ] ], 0.25 ] - ], - [ - [ [ [ -8, 7, 0, 3, -2, 2 ], [ -8, 8, 0, 4, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -7, 8, 0, 3, -2, 2 ] ], 0 ], - [ [ [ -8, 7, 0, 3, -2, 2 ], [ -8, 8, 0, 3, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -7, 8, 0, 3, -2, 2 ] ], 0 ], - [ [ [ -8, 7, 0, 3, -2, 2 ], [ -8, 8, 0, 3, -2, 2 ], [ -7, 7, 0, 3, -2, 2 ], [ -7, 8, 0, 3, -2, 2 ] ], 0.25 ], - [ [ [ -8, 7, 0, 3, -2, 2 ], [ -8, 7, 0, 3, -2, 3 ], [ -7, 7, 0, 3, -2, 2 ], [ -7, 8, 0, 3, -2, 2 ] ], 0 ], - [ [ [ -8, 7, 0, 3, -2, 2 ], [ -8, 7, 0, 3, -2, 3 ], [ -7, 7, 0, 3, -2, 2 ], [ -7, 7, 0, 3, -2, 3 ] ], 0.25 ], - [ [ [ -8, 7, 0, 3, -2, 2 ], [ -8, 7, 0, 3, -2, 3 ], [ -7, 7, 0, 3, -2, 2 ], [ -7, 7, 0, 4, -2, 2 ] ], 0.25 ] - ], - [ - [ [ [ -8, 7, 0, 3, -2, 2 ], [ -8, 7, 0, 3, -2, 3 ], [ -8, 7, 0, 3, -1, 3 ], [ -7, 7, 0, 4, -2, 2 ] ], 0 ], - [ [ [ -8, 7, 0, 3, -2, 2 ], [ -8, 7, 0, 3, -2, 3 ], [ -8, 7, 0, 3, -1, 3 ], [ -6, 7, 0, 3, -2, 2 ] ], 0 ], - [ [ [ -9, 7, 0, 3, -1, 3 ], [ -8, 7, 0, 3, -2, 3 ], [ -8, 7, 0, 3, -1, 3 ], [ -6, 7, 0, 3, -2, 2 ] ], 0.25 ] - ], - [ - [ [ [ -9, 7, 0, 3, -1, 3 ], [ -8, 7, 0, 3, -2, 3 ], [ -7, 7, 1, 3, -2, 2 ], [ -6, 7, 0, 3, -2, 2 ] ], 0 ], - [ [ [ -9, 7, 0, 3, -1, 3 ], [ -7, 7, 0, 3, -2, 2 ], [ -7, 7, 1, 3, -2, 2 ], [ -6, 7, 0, 3, -2, 2 ] ], 0.25 ], - [ [ [ -9, 7, 0, 3, -1, 3 ], [ -7, 7, 0, 3, -2, 2 ], [ -7, 7, 0, 3, -1, 2 ], [ -6, 7, 0, 3, -2, 2 ] ], 0.25 ], - [ [ [ -9, 7, 0, 3, -1, 3 ], [ -7, 7, 0, 3, -2, 2 ], [ -8, 8, 0, 3, -2, 2 ], [ -6, 7, 0, 3, -2, 2 ] ], 0.25 ], - [ [ [ -9, 7, 0, 3, -1, 3 ], [ -8, 7, 0, 3, -1, 3 ], [ -8, 8, 0, 3, -2, 2 ], [ -6, 7, 0, 3, -2, 2 ] ], 0.25 ] - ], - [ - [ [ [ -9, 7, 0, 3, -1, 3 ], [ -8, 7, 0, 3, -1, 3 ], [ -8, 8, 0, 3, -2, 2 ], [ -7, 7, 0, 3, -1, 3 ] ], 0.25 ], - [ [ [ -9, 7, 0, 3, -1, 3 ], [ -8, 8, 0, 3, -2, 3 ], [ -8, 8, 0, 3, -2, 2 ], [ -7, 7, 0, 3, -1, 3 ] ], 0.25 ], - [ [ [ -9, 7, 0, 3, -1, 3 ], [ -8, 8, 0, 3, -2, 3 ], [ -8, 8, 0, 3, -2, 2 ], [ -7, 8, 0, 3, -2, 3 ] ], 0.25 ], - [ [ [ -9, 7, 0, 3, -1, 3 ], [ -8, 8, 0, 4, -2, 2 ], [ -8, 8, 0, 3, -2, 2 ], [ -7, 8, 0, 3, -2, 3 ] ], 0.25 ], - [ [ [ -9, 7, 0, 3, -1, 3 ], [ -7, 8, 0, 3, -2, 2 ], [ -8, 8, 0, 3, -2, 2 ], [ -7, 8, 0, 3, -2, 3 ] ], 0.25 ] - ], - [ - [ [ [ -9, 7, 0, 3, -1, 3 ], [ -8, 8, 1, 3, -2, 2 ], [ -8, 8, 0, 3, -2, 2 ], [ -7, 8, 0, 3, -2, 3 ] ], 0 ], - [ [ [ -9, 7, 0, 3, -1, 3 ], [ -8, 8, 1, 3, -2, 2 ], [ -8, 8, 0, 3, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0 ], - [ [ [ -8, 8, -1, 3, -2, 2 ], [ -8, 8, 1, 3, -2, 2 ], [ -8, 8, 0, 3, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0.25 ], - [ [ [ -8, 8, -1, 3, -2, 2 ], [ -7, 7, 0, 3, -2, 2 ], [ -8, 8, 0, 3, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0 ], - [ [ [ -9, 8, 0, 4, -2, 2 ], [ -7, 7, 0, 3, -2, 2 ], [ -8, 8, 0, 3, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0.25 ], - [ [ [ -9, 8, 0, 3, -2, 2 ], [ -7, 7, 0, 3, -2, 2 ], [ -8, 8, 0, 3, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0.25 ] - ], - [ - [ [ [ -9, 8, 0, 3, -2, 2 ], [ -7, 7, 0, 3, -2, 2 ], [ -8, 8, 0, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0 ], - [ [ [ -9, 8, 0, 4, -2, 1 ], [ -7, 7, 0, 3, -2, 2 ], [ -8, 8, 0, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0.625 ], - [ [ [ -9, 8, 0, 4, -2, 1 ], [ -9, 8, 0, 4, -2, 2 ], [ -8, 8, 0, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0 ], - [ [ [ -10, 8, 0, 4, -2, 2 ], [ -9, 8, 0, 4, -2, 2 ], [ -8, 8, 0, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0.25 ], - [ [ [ -10, 8, 0, 4, -2, 2 ], [ -9, 9, 0, 4, -2, 2 ], [ -8, 8, 0, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0.25 ], - [ [ [ -10, 8, 0, 4, -2, 2 ], [ -8, 8, -1, 4, -2, 2 ], [ -8, 8, 0, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0.25 ], - [ [ [ -10, 8, 0, 4, -2, 2 ], [ -8, 8, -1, 4, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0.25 ] - ], - [ - [ [ [ -9, 8, 0, 3, -2, 2 ], [ -8, 8, -1, 4, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0 ], - [ [ [ -9, 8, 0, 3, -2, 2 ], [ -8, 8, -1, 4, -2, 2 ], [ -9, 9, 0, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0 ], - [ [ [ -9, 8, 0, 3, -2, 2 ], [ -9, 8, 0, 4, -2, 2 ], [ -9, 9, 0, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0.25 ], - [ [ [ -9, 8, 0, 3, -2, 2 ], [ -8, 8, 0, 3, -2, 2 ], [ -9, 9, 0, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0.25 ], - [ [ [ -9, 8, 0, 3, -2, 2 ], [ -8, 8, 0, 4, -2, 2 ], [ -9, 9, 0, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0 ], - [ [ [ -9, 8, 0, 4, -2, 2 ], [ -8, 8, 0, 4, -2, 2 ], [ -9, 9, 0, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0.25 ] - ], - [ - [ [ [ -9, 8, 0, 4, -2, 2 ], [ -8, 8, 0, 4, -2, 2 ], [ -8, 8, -1, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0.25 ], - [ [ [ -9, 8, 0, 4, -2, 2 ], [ -7, 8, -1, 4, -2, 2 ], [ -8, 8, -1, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0 ], - [ [ [ -9, 8, -1, 4, -2, 2 ], [ -7, 8, -1, 4, -2, 2 ], [ -8, 8, -1, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0.25 ] - ], - [ - [ [ [ -9, 8, -1, 4, -2, 2 ], [ -7, 8, -1, 4, -2, 2 ], [ -9, 9, -1, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0 ], - [ [ [ -7, 8, 0, 4, -3, 2 ], [ -7, 8, -1, 4, -2, 2 ], [ -9, 9, -1, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0.25 ], - [ [ [ -7, 8, 0, 4, -3, 2 ], [ -7, 8, -1, 4, -2, 2 ], [ -8, 7, 0, 4, -2, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0.25 ], - [ [ [ -7, 8, 0, 4, -3, 2 ], [ -7, 8, -1, 4, -2, 2 ], [ -8, 8, 0, 4, -3, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0.25 ] - ], - [ - [ [ [ -7, 8, 0, 4, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -8, 8, 0, 4, -3, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0.25 ], - [ [ [ -7, 8, 0, 4, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -7, 8, -1, 4, -3, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0.25 ] - ], - [ - [ [ [ -7, 8, 0, 4, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -6, 6, 0, 4, -3, 2 ], [ -7, 8, 0, 4, -2, 2 ] ], 0 ], - [ [ [ -7, 8, 0, 4, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -6, 6, 0, 4, -3, 2 ], [ -7, 6, 0, 4, -3, 2 ] ], 0.25 ], - [ [ [ -8, 6, 0, 4, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -6, 6, 0, 4, -3, 2 ], [ -7, 6, 0, 4, -3, 2 ] ], 0.25 ] - ], - [ - [ [ [ -8, 7, 0, 4, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -6, 6, 0, 4, -3, 2 ], [ -7, 6, 0, 4, -3, 2 ] ], 0 ], - [ [ [ -8, 7, 0, 4, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ], [ -7, 6, 0, 4, -3, 2 ] ], 0 ], - [ [ [ -8, 7, 0, 4, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ], [ -8, 8, 0, 4, -3, 2 ] ], 0.25 ], - [ [ [ -8, 7, 0, 4, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -6, 7, -1, 4, -3, 2 ], [ -8, 8, 0, 4, -3, 2 ] ], 0 ], - [ [ [ -8, 7, 0, 4, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -6, 7, -1, 4, -3, 2 ], [ -7, 7, -1, 4, -3, 2 ] ], 0 ], - [ [ [ -8, 7, -1, 4, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -6, 7, -1, 4, -3, 2 ], [ -7, 7, -1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -8, 7, -1, 4, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -6, 7, -1, 4, -3, 2 ], [ -6, 7, 0, 3, -3, 2 ] ], 0.25 ] - ], - [ - [ [ [ -8, 7, -1, 4, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -7, 7, 0, 5, -3, 2 ], [ -6, 7, 0, 3, -3, 2 ] ], 0 ], - [ [ [ -9, 7, 0, 5, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -7, 7, 0, 5, -3, 2 ], [ -6, 7, 0, 3, -3, 2 ] ], 0.25 ], - [ [ [ -9, 7, 0, 5, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -7, 7, 0, 5, -3, 2 ], [ -6, 7, -1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -9, 7, 0, 5, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -7, 7, 0, 5, -3, 2 ], [ -8, 7, 0, 5, -3, 2 ] ], 0 ], - [ [ [ -9, 7, 0, 5, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -6, 7, 0, 4, -3, 2 ], [ -8, 7, 0, 5, -3, 2 ] ], 0.25 ], - [ [ [ -9, 7, 0, 5, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ], [ -8, 7, 0, 5, -3, 2 ] ], 0 ], - [ [ [ -8, 7, 0, 4, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ], [ -8, 7, 0, 5, -3, 2 ] ], 0.25 ] - ], - [ - [ [ [ -8, 7, 0, 4, -3, 2 ], [ -8, 9, 0, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ], [ -8, 7, 0, 5, -3, 2 ] ], 0 ], - [ [ [ -9, 9, 0, 4, -3, 2 ], [ -8, 9, 0, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ], [ -8, 7, 0, 5, -3, 2 ] ], 0 ], - [ [ [ -9, 9, 0, 4, -3, 2 ], [ -8, 9, 0, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -9, 9, 0, 4, -3, 2 ], [ -7, 8, -1, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -9, 8, 0, 4, -3, 2 ], [ -7, 8, -1, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -9, 8, 0, 4, -3, 2 ], [ -8, 8, 0, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -9, 8, 0, 4, -3, 2 ], [ -9, 8, 1, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -10, 8, 1, 4, -3, 2 ], [ -9, 8, 1, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ] ], 0.25 ] - ], - [ - [ [ [ -10, 8, 1, 4, -3, 2 ], [ -9, 8, 1, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ], [ -7, 7, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -10, 8, 1, 4, -3, 2 ], [ -8, 8, 1, 3, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ], [ -7, 7, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -10, 8, 1, 4, -3, 2 ], [ -8, 8, 1, 3, -3, 2 ], [ -8, 9, 1, 4, -3, 2 ], [ -7, 7, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -10, 8, 1, 4, -3, 2 ], [ -8, 8, 1, 3, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ], [ -7, 7, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -10, 8, 1, 4, -3, 2 ], [ -9, 9, 1, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ], [ -7, 7, 1, 4, -3, 2 ] ], 0.25 ] - ], - [ - [ [ [ -9, 8, 1, 4, -3, 2 ], [ -9, 9, 1, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ], [ -7, 7, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -9, 8, 1, 4, -3, 2 ], [ -9, 9, 1, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -7, 7, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -8, 7, 0, 4, -3, 2 ], [ -9, 9, 1, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -7, 7, 1, 4, -3, 2 ] ], 0.25 ] - ], - [ - [ [ [ -8, 7, 0, 4, -3, 2 ], [ -8, 7, 2, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -7, 7, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -8, 7, 0, 4, -3, 2 ], [ -8, 7, 2, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -7, 8, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -9, 7, 1, 4, -3, 2 ], [ -8, 7, 2, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -7, 8, 1, 4, -3, 2 ] ], 0.25 ] - ], - [ - [ [ [ -8, 6, 1, 4, -3, 2 ], [ -8, 7, 2, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -7, 8, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -8, 6, 1, 4, -3, 2 ], [ -8, 7, 2, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -6, 6, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -8, 6, 1, 4, -3, 2 ], [ -7, 6, 1, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -6, 6, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -9, 8, 1, 4, -3, 2 ], [ -7, 6, 1, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -6, 6, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -7, 7, 1, 4, -3, 2 ], [ -7, 6, 1, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -6, 6, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -7, 7, 1, 4, -3, 2 ], [ -7, 6, 1, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -7, 8, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -7, 7, 1, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -7, 8, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -7, 7, 1, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -7, 7, 1, 4, -2, 2 ] ], 0.25 ] - ], - [ - [ [ [ -7, 7, 1, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -7, 8, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -9, 7, 1, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -7, 8, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -9, 7, 1, 4, -3, 2 ], [ -7, 7, 1, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -7, 8, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -9, 8, 1, 4, -3, 2 ], [ -7, 7, 1, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -7, 8, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -9, 8, 1, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -7, 8, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -9, 8, 1, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -7, 7, 1, 4, -3, 2 ] ], 0.25 ] - ], - [ - [ [ [ -9, 8, 1, 4, -3, 2 ], [ -7, 8, 1, 3, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -7, 7, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -9, 8, 1, 4, -3, 2 ], [ -7, 8, 1, 3, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ], [ -8, 9, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -9, 8, 1, 4, -3, 2 ], [ -7, 8, 1, 3, -3, 2 ], [ -9, 9, 1, 4, -3, 2 ], [ -8, 9, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -9, 8, 1, 4, -3, 2 ], [ -8, 8, 2, 4, -3, 2 ], [ -9, 9, 1, 4, -3, 2 ], [ -8, 9, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -9, 8, 1, 4, -3, 2 ], [ -7, 7, 1, 4, -3, 2 ], [ -9, 9, 1, 4, -3, 2 ], [ -8, 9, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -9, 8, 1, 4, -3, 2 ], [ -7, 7, 1, 4, -3, 2 ], [ -9, 9, 1, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -9, 8, 1, 4, -3, 2 ], [ -7, 7, 1, 4, -3, 2 ], [ -9, 9, 1, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ] ], 0.25 ] - ], - [ - [ [ [ -9, 8, 1, 4, -3, 2 ], [ -7, 7, 1, 4, -3, 2 ], [ -8, 7, 2, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -9, 8, 1, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ], [ -8, 7, 2, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -9, 7, 1, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ], [ -8, 7, 2, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -9, 7, 1, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ], [ -7, 7, 1, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -9, 7, 1, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ], [ -7, 8, 1, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ] ], 0.25 ], - [ [ [ -10, 8, 1, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ], [ -7, 8, 1, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -10, 8, 1, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ], [ -6, 7, 0, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ] ], 0.25 ] - ], - [ - [ [ [ -9, 7, 0, 4, -3, 2 ], [ -8, 8, 1, 4, -3, 2 ], [ -6, 7, 0, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -9, 7, 0, 4, -3, 2 ], [ -8, 7, 0, 4, -3, 2 ], [ -6, 7, 0, 4, -3, 2 ], [ -8, 7, 1, 4, -3, 2 ] ], 0 ], - [ [ [ -9, 7, 0, 4, -3, 2 ], [ -8, 7, 0, 4, -3, 2 ], [ -6, 7, 0, 4, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ] ], 0.25 ], - [ [ [ -9, 8, 0, 4, -3, 2 ], [ -8, 7, 0, 4, -3, 2 ], [ -6, 7, 0, 4, -3, 2 ], [ -7, 7, 0, 4, -3, 2 ] ], 0.25 ] - ], - [ - [ [ [ -9, 8, 0, 4, -3, 2 ], [ -8, 7, 0, 4, -3, 2 ], [ -6, 7, 0, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ] ], 0.25 ], - [ [ [ -9, 8, 0, 4, -3, 2 ], [ -8, 7, 0, 4, -3, 2 ], [ -8, 8, 0, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ] ], 0 ], - [ [ [ -9, 8, 0, 4, -3, 2 ], [ -9, 9, 0, 4, -3, 2 ], [ -8, 8, 0, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ] ], 0.25 ], - [ [ [ -9, 8, 0, 4, -3, 2 ], [ -9, 9, 0, 4, -3, 2 ], [ -8, 9, 0, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ] ], 0 ], - [ [ [ -9, 8, 0, 4, -3, 2 ], [ -9, 9, 0, 4, -3, 2 ], [ -8, 9, 0, 4, -3, 2 ], [ -7, 9, 0, 4, -3, 2 ] ], 0.25 ], - [ [ [ -9, 8, 0, 4, -3, 2 ], [ -9, 9, 0, 4, -3, 2 ], [ -8, 9, 0, 4, -3, 2 ], [ -8, 8, 0, 4, -3, 2 ] ], 0.25 ] - ] - ] -], -"last_changes": -[ - [ [ -9, 8, 0, 4, -3, 2 ], [ -8, 7, 0, 4, -3, 2 ], [ -8, 8, 0, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ] ], - [ [ -9, 8, 0, 4, -3, 2 ], [ -9, 9, 0, 4, -3, 2 ], [ -8, 8, 0, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ] ], - [ [ -9, 8, 0, 4, -3, 2 ], [ -9, 9, 0, 4, -3, 2 ], [ -8, 9, 0, 4, -3, 2 ], [ -7, 8, 0, 4, -3, 2 ] ], - [ [ -9, 8, 0, 4, -3, 2 ], [ -9, 9, 0, 4, -3, 2 ], [ -8, 9, 0, 4, -3, 2 ], [ -7, 9, 0, 4, -3, 2 ] ], - [ [ -9, 8, 0, 4, -3, 2 ], [ -9, 9, 0, 4, -3, 2 ], [ -8, 9, 0, 4, -3, 2 ], [ -8, 8, 0, 4, -3, 2 ] ] -], -"cur_uid": "615c4008", -"ref_uid": "7276dc78", -"order_seed": 913894, -"dur_seed": 642726, -"motifs_seed": 376961, -"entrances_probs_vals": [ 0.66, 0, 0, 0, 1, 0.019607843137255, 0, 0.2156862745098, 0, 0.2516339869281, 0.76351351351351, 0.31045751633987, 0, 0.46732026143791, 0, 0.50326797385621, 0, 0.5359477124183, 0, 1, 0 ], -"passages_probs_vals": [ 0.66, 0, 0, 0, 1, 0.019607843137255, 0, 0.2156862745098, 0, 0.2516339869281, 0.76351351351351, 0.31045751633987, 0, 0.46732026143791, 0, 0.50326797385621, 0, 0.5359477124183, 0, 1, 0 ], -"exits_probs_vals": [ 0.66, 0, 0, 0, 1, 0.019607843137255, 0, 0.2156862745098, 0, 0.2516339869281, 0.76351351351351, 0.31045751633987, 0, 0.46732026143791, 0, 0.50326797385621, 0, 0.5359477124183, 0, 1, 0 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1452.6315789474 ], [ -702, 1694.1176470588 ], [ -702, 1972.7554179567 ] ], -"step_probs_vals": [ -1200, 1200, 0.0041152263374486, 0.0056818181818179, 0.080246913580247, 0.02840909090909, 0.20781893004115, 0.028409090909091, 0.41152263374486, 0, 0.44650205761317, 0.16477272727273, 0.47736625514403, 0, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.7880658436214, 0.034090909090909, 1, 0.034090909090909 ], -"passages_weights": [ 0.58, 1, 0.43, 1, 0.82 ], -"hd_exp": 10, -"hd_invert": 0, -"order": -[ - [ [ 3 ], [ 1, 0, 2, 1, 1, 1 ], [ ] ], - [ [ 2 ], [ 1, 3, 0, 1 ], [ ] ], - [ [ 1 ], [ 2, 3, 0 ], [ ] ], - [ [ 2 ], [ 1, 0, 3, 0, 1, 3, 1 ], [ ] ], - [ [ 0, 2 ], [ 3, 1, 1, 3, 3, 3 ], [ ] ], - [ [ 0 ], [ 3, 1, 2, 1, 3, 3 ], [ ] ], - [ [ 1 ], [ 2, 3, 0 ], [ ] ], - [ [ 3, 0 ], [ 2, 1, 2, 2, 1 ], [ ] ], - [ [ 2, 0 ], [ 3, 1, 3, 1, 1 ], [ ] ], - [ [ 2 ], [ 1, 3, 0, 1, 0, 0 ], [ ] ], - [ [ 3 ], [ 2, 0, 1, 0, 1, 1, 2 ], [ ] ], - [ [ 3 ], [ 0, 2, 1, 1, 1, 0 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ], - [ [ 1, 3 ], [ 2, 0, 2, 2 ], [ ] ], - [ [ 0, 3 ], [ 1, 2 ], [ ] ], - [ [ 1 ], [ 2, 3, 0 ], [ ] ], - [ [ 1 ], [ 0, 2, 3, 2, 3, 0, 3 ], [ ] ], - [ [ 1 ], [ 2, 0, 3, 3, 2, 2, 0 ], [ ] ], - [ [ 2 ], [ 1, 0, 3, 1, 0, 1, 1, 0 ], [ ] ], - [ [ 0 ], [ 3, 1, 2, 2, 1 ], [ ] ], - [ [ 1, 3 ], [ 0, 2, 0 ], [ ] ], - [ [ 2 ], [ 1, 3, 0 ], [ ] ], - [ [ 2 ], [ 0, 3, 1, 0, 0, 3, 1, 3 ], [ ] ], - [ [ 2 ], [ 3, 0, 1, 0, 1, 3 ], [ ] ], - [ [ 0 ], [ 1, 3, 2, 1, 1, 3, 3 ], [ ] ], - [ [ 3 ], [ 2, 1, 0, 2, 2, 0, 2 ], [ ] ], - [ [ 2 ], [ 0, 1, 3, 0 ], [ ] ], - [ [ 0 ], [ 3, 2, 1, 2, 3, 3 ], [ ] ] -], -"sus_weights": [ 0.69, 0.17, 0 ], -"order_size": [ 28.275510204082, 28.275510204082 ], -"passages_size": [ 0, 6 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/6522664c_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/6522664c_code.scd deleted file mode 100644 index 42b64ff..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/6522664c_code.scd +++ /dev/null @@ -1,981 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - /* - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - */ - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - //lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - lastState = if(o == 0, {lastXChanges.last.deepCopy}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - /* - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - */ - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - //# voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - # voices, durs = seq.flatten2(if(oneShot, {2}, {3})).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(2).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/6522664c_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/6522664c_mus_model.json deleted file mode 100644 index e6c59fc..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/6522664c_mus_model.json +++ /dev/null @@ -1,85 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -4, 2, 2, 2, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -4, 2, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 2, 2, 2, 1, 0 ], [ -3, 1, 1, 3, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -3, 1, 1, 2, 1, 0 ], [ -3, 1, 1, 3, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -3, 1, 1, 2, 1, 0 ], [ -3, 1, 1, 3, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 1, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 1, 2, 1, 0 ], [ -3, 1, 1, 3, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 1, 2, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 1, 2, 1, 0 ], [ -3, 1, 1, 3, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -3, 2, 1, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 1, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 1, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 1, 2, 1, 0 ], [ -3, 1, 3, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ], - [ [ [ -2, 0, 2, 2, 1, 0 ], [ -3, 1, 3, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ], - [ [ [ -2, 0, 2, 2, 1, 0 ], [ -3, 1, 3, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 2, 2, 1, 0 ], [ -3, 1, 3, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ], - [ [ [ -3, 2, 2, 2, 1, 0 ], [ -3, 1, 3, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -4, 3, 2, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 2, 2, 1, 0 ], [ -5, 3, 1, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -4, 3, 2, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 2, 2, 1, 0 ], [ -5, 3, 2, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -4, 3, 2, 2, 1, 0 ] ], 1 ], - [ [ [ -3, 2, 2, 2, 1, 0 ], [ -5, 3, 2, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -4, 2, 1, 2, 1, 0 ], [ -5, 3, 2, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 3, 1, 2, 1, 0 ], [ -5, 3, 2, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ] ], 1 ] - ] - ] -], -"last_changes": -[ - [ [ -3, 2, 2, 2, 1, 0 ], [ -5, 3, 1, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -4, 3, 2, 2, 1, 0 ] ], - [ [ -3, 2, 2, 2, 1, 0 ], [ -5, 3, 2, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -4, 3, 2, 2, 1, 0 ] ], - [ [ -3, 2, 2, 2, 1, 0 ], [ -5, 3, 2, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ] ], - [ [ -4, 2, 1, 2, 1, 0 ], [ -5, 3, 2, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ] ], - [ [ -4, 3, 1, 2, 1, 0 ], [ -5, 3, 2, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ] ] -], -"cur_uid": "6522664c", -"ref_uid": "4bf1af12", -"order_seed": 347999, -"dur_seed": 441379, -"motifs_seed": 667646, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ 0, 1200, 0.0061728395061728, 0.10227272727273, 0.074074074074074, 0.10227272727273, 0.2037037037037, 0.090909090909091, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.7880658436214, 0.034090909090909, 1, 0.034090909090909 ], -"passages_weights": [ 1, 0.47, 0.43, 1, 0.8 ], -"hd_exp": 8, -"hd_invert": 0, -"order": -[ - [ [ 2, 0 ], [ 3, 1 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ], - [ [ 2, 0 ], [ 3, 1 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 3 ], [ 1, 0, 2 ], [ ] ], - [ [ 2, 1 ], [ 0, 3 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 2 ], [ 1, 3, 0 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 10.091836734694, 10.091836734694 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/lilypond/part_I.ly deleted file mode 100644 index aa8c464..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/lilypond/part_I.ly +++ /dev/null @@ -1,20 +0,0 @@ -{ - { g'1^\markup { \pad-markup #0.2 "-21"} ~ } - \bar "|" - { g'1 } - \bar "|" - { fis1^\markup { \pad-markup #0.2 "+26"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }} } - \bar "|" - { c'1^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} } - \bar "|" - { e'1^\markup { \pad-markup #0.2 "-36"} ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'2 fis'2^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { fis'1 } - \bar "|" - { g'1^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/lilypond/part_II.ly deleted file mode 100644 index 9007135..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/lilypond/part_II.ly +++ /dev/null @@ -1,20 +0,0 @@ -{ - { c''1^\markup { \pad-markup #0.2 "-23"} ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''2 b2^\markup { \pad-markup #0.2 "-34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }} ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/lilypond/part_III.ly deleted file mode 100644 index 77f3a11..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/lilypond/part_III.ly +++ /dev/null @@ -1,20 +0,0 @@ -{ - { g2^\markup { \pad-markup #0.2 "-21"} e'2^\markup { \pad-markup #0.2 "-36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} } - \bar "|" - { a'1^\markup { \pad-markup #0.2 "+46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }} ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'2 b'2^\markup { \pad-markup #0.2 "-34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { b'2 g'2^\markup { \pad-markup #0.2 "+50"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }} ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 } - \bar "|" - { d2^\markup { \pad-markup #0.2 "-19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }} fis2^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { fis1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/lilypond/part_IV.ly deleted file mode 100644 index 49e5ac8..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6522664c/lilypond/part_IV.ly +++ /dev/null @@ -1,20 +0,0 @@ -{ - { b1^\markup { \pad-markup #0.2 "-34"} ~ } - \bar "|" - { b2 c'2^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } - \bar "|" - { c'2 g'2^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }} ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 } - \bar "|" - { a'1^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }} } - \bar "|" - { b'1^\markup { \pad-markup #0.2 "-34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'2 g2^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/6db2efcc_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/6db2efcc_code.scd deleted file mode 100644 index 42b64ff..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/6db2efcc_code.scd +++ /dev/null @@ -1,981 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - /* - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - */ - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - //lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - lastState = if(o == 0, {lastXChanges.last.deepCopy}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - /* - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - */ - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - //# voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - # voices, durs = seq.flatten2(if(oneShot, {2}, {3})).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(2).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/6db2efcc_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/6db2efcc_mus_model.json deleted file mode 100644 index d66bfdd..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/6db2efcc_mus_model.json +++ /dev/null @@ -1,86 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -5, 2, 3, 3, 1, 0 ], [ -6, 2, 4, 3, 1, 0 ], [ -6, 3, 3, 4, 1, 0 ], [ -6, 2, 3, 4, 1, 0 ] ], 1 ], - [ [ [ -5, 2, 3, 3, 1, 0 ], [ -6, 2, 3, 3, 2, 0 ], [ -6, 3, 3, 4, 1, 0 ], [ -6, 2, 3, 4, 1, 0 ] ], 1 ], - [ [ [ -5, 2, 3, 3, 1, 0 ], [ -6, 2, 3, 3, 2, 0 ], [ -4, 1, 3, 3, 1, 0 ], [ -6, 2, 3, 4, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 2, 3, 3, 1, 0 ], [ -6, 2, 3, 3, 2, 0 ], [ -4, 1, 3, 3, 1, 0 ], [ -4, 2, 3, 3, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 2, 3, 3, 1, 0 ], [ -6, 2, 3, 3, 2, 0 ], [ -4, 1, 3, 3, 1, 0 ], [ -4, 2, 3, 2, 2, 0 ] ], 1 ], - [ [ [ -6, 2, 3, 4, 2, 0 ], [ -6, 2, 3, 3, 2, 0 ], [ -4, 1, 3, 3, 1, 0 ], [ -4, 2, 3, 2, 2, 0 ] ], 1 ], - [ [ [ -6, 2, 3, 4, 2, 0 ], [ -6, 2, 3, 3, 2, 0 ], [ -5, 2, 3, 3, 2, 0 ], [ -4, 2, 3, 2, 2, 0 ] ], 1 ] - ], - [ - [ [ [ -6, 2, 3, 4, 2, 0 ], [ -6, 2, 3, 3, 2, 0 ], [ -4, 1, 3, 2, 2, 0 ], [ -4, 2, 3, 2, 2, 0 ] ], 1 ], - [ [ [ -4, 2, 2, 2, 2, 0 ], [ -6, 2, 3, 3, 2, 0 ], [ -4, 1, 3, 2, 2, 0 ], [ -4, 2, 3, 2, 2, 0 ] ], 1 ], - [ [ [ -4, 2, 2, 2, 2, 0 ], [ -5, 2, 3, 2, 2, 0 ], [ -4, 1, 3, 2, 2, 0 ], [ -4, 2, 3, 2, 2, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 2, 3, 2, 2, 1 ], [ -5, 2, 3, 2, 2, 0 ], [ -4, 1, 3, 2, 2, 0 ], [ -4, 2, 3, 2, 2, 0 ] ], 1 ], - [ [ [ -5, 2, 3, 2, 2, 1 ], [ -5, 2, 3, 2, 2, 0 ], [ -3, 2, 3, 1, 2, 0 ], [ -4, 2, 3, 2, 2, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 3, 1, 1, 0 ], [ -5, 2, 3, 2, 2, 0 ], [ -3, 2, 3, 1, 2, 0 ], [ -4, 2, 3, 2, 2, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 3, 1, 1, 0 ], [ -5, 2, 3, 2, 2, 0 ], [ -3, 2, 3, 2, 2, -1 ], [ -4, 2, 3, 2, 2, 0 ] ], 1 ], - [ [ [ -3, 2, 3, 1, 1, 0 ], [ -5, 2, 3, 2, 2, 0 ], [ -3, 2, 3, 2, 2, -1 ], [ -3, 2, 4, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -3, 2, 3, 1, 1, 0 ], [ -5, 2, 3, 2, 2, 0 ], [ -5, 2, 4, 2, 1, 0 ], [ -3, 2, 4, 1, 1, 0 ] ], 1 ], - [ [ [ -3, 2, 3, 1, 1, 0 ], [ -3, 2, 4, 0, 1, 0 ], [ -5, 2, 4, 2, 1, 0 ], [ -3, 2, 4, 1, 1, 0 ] ], 1 ], - [ [ [ -4, 2, 4, 2, 1, 0 ], [ -3, 2, 4, 0, 1, 0 ], [ -5, 2, 4, 2, 1, 0 ], [ -3, 2, 4, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 2, 4, 2, 1, 0 ], [ -3, 2, 4, 0, 1, 0 ], [ -4, 2, 3, 2, 1, 0 ], [ -3, 2, 4, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -4, 2, 4, 2, 1, 0 ], [ -3, 2, 3, 2, 1, -1 ], [ -4, 2, 3, 2, 1, 0 ], [ -3, 2, 4, 1, 1, 0 ] ], 1 ] - ] - ] -], -"last_changes": -[ - [ [ -3, 2, 3, 1, 1, 0 ], [ -5, 2, 3, 2, 2, 0 ], [ -5, 2, 4, 2, 1, 0 ], [ -3, 2, 4, 1, 1, 0 ] ], - [ [ -3, 2, 3, 1, 1, 0 ], [ -3, 2, 4, 0, 1, 0 ], [ -5, 2, 4, 2, 1, 0 ], [ -3, 2, 4, 1, 1, 0 ] ], - [ [ -4, 2, 4, 2, 1, 0 ], [ -3, 2, 4, 0, 1, 0 ], [ -5, 2, 4, 2, 1, 0 ], [ -3, 2, 4, 1, 1, 0 ] ], - [ [ -4, 2, 4, 2, 1, 0 ], [ -3, 2, 4, 0, 1, 0 ], [ -4, 2, 3, 2, 1, 0 ], [ -3, 2, 4, 1, 1, 0 ] ], - [ [ -4, 2, 4, 2, 1, 0 ], [ -3, 2, 3, 2, 1, -1 ], [ -4, 2, 3, 2, 1, 0 ], [ -3, 2, 4, 1, 1, 0 ] ] -], -"cur_uid": "6db2efcc", -"ref_uid": "521654f8", -"order_seed": 213803, -"dur_seed": 264333, -"motifs_seed": 980711, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ 0, 1200, 0.0061728395061728, 0.10227272727273, 0.074074074074074, 0.10227272727273, 0.2037037037037, 0.090909090909091, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.7880658436214, 0.034090909090909, 1, 0.034090909090909 ], -"passages_weights": [ 1, 0.47, 0.43, 1, 0.5 ], -"hd_exp": 5, -"hd_invert": 0, -"order": -[ - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 1 ], [ 3, 0, 2 ], [ ] ], - [ [ 3 ], [ 2, 0, 1 ], [ ] ], - [ [ 3, 1 ], [ 0, 2 ], [ ] ], - [ [ 1, 2, 3 ], [ 0 ], [ ] ], - [ [ 1, 0 ], [ 2, 3 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ], - [ [ 0, 1, 3 ], [ 2 ], [ ] ], - [ [ 3, 2, 0 ], [ 1 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 10.091836734694, 10.091836734694 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/lilypond/part_I.ly deleted file mode 100644 index 90f111c..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/lilypond/part_I.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { ais1^\markup { \pad-markup #0.2 "-11"} ~ } - \bar "|" - { ais2 g'2^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }} } - \bar "|" - { gis'1^\markup { \pad-markup #0.2 "+3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }} ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 } - \bar "|" - { a'1^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/lilypond/part_II.ly deleted file mode 100644 index 88a941a..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/lilypond/part_II.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { f'1^\markup { \pad-markup #0.2 "-9"} } - \bar "|" - { f'1^\markup { \pad-markup #0.2 "+19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { f'1 } - \bar "|" - { fis'2^\markup { \pad-markup #0.2 "-28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} cis'2^\markup { \pad-markup #0.2 "+1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }} ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'2 ais'2^\markup { \pad-markup #0.2 "+34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }} ~ } - \bar "|" - { ais'2 c''2^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↓" }} ~ } - \bar "|" - { c''2 fis2^\markup { \pad-markup #0.2 "+38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }} ~ } - \bar "|" - { fis1 } - \bar "|" - { dis'1^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/lilypond/part_III.ly deleted file mode 100644 index 898501b..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/lilypond/part_III.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { e2^\markup { \pad-markup #0.2 "+7"} fis2^\markup { \pad-markup #0.2 "-28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }} ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis2 gis2^\markup { \pad-markup #0.2 "+3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { gis1 ~ } - \bar "|" - { gis1 ~ } - \bar "|" - { gis1 } - \bar "|" - { b1^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↓" }} ~ } - \bar "|" - { b2 fis'2^\markup { \pad-markup #0.2 "+11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↓" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/lilypond/part_IV.ly deleted file mode 100644 index 6098652..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/6db2efcc/lilypond/part_IV.ly +++ /dev/null @@ -1,22 +0,0 @@ -{ - { c'1^\markup { \pad-markup #0.2 "+21"} ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'2 dis'2^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }} ~ } - \bar "|" - { dis'1 } - \bar "|" - { e'1^\markup { \pad-markup #0.2 "+17"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }} } - \bar "|" - { e'1^\markup { \pad-markup #0.2 "+44"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }} } - \bar "|" - { f'1^\markup { \pad-markup #0.2 "-17"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↓" }} ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'2 fis'2^\markup { \pad-markup #0.2 "+38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } - \bar "|" - { fis'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/7276dc78_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/7276dc78_code.scd deleted file mode 100644 index 42b64ff..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/7276dc78_code.scd +++ /dev/null @@ -1,981 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - /* - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - */ - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - //lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - lastState = if(o == 0, {lastXChanges.last.deepCopy}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - /* - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - */ - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - //# voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - # voices, durs = seq.flatten2(if(oneShot, {2}, {3})).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(2).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/7276dc78_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/7276dc78_mus_model.json deleted file mode 100644 index 6d0340b..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/7276dc78_mus_model.json +++ /dev/null @@ -1,158 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -7, 6, 4, -1, 1, 2 ], [ -5, 5, 4, 0, 0, 2 ], [ -6, 6, 4, 0, 0, 2 ], [ -6, 6, 4, 0, 1, 2 ] ], 1 ], - [ [ [ -6, 6, 4, -1, 0, 2 ], [ -5, 5, 4, 0, 0, 2 ], [ -6, 6, 4, 0, 0, 2 ], [ -6, 6, 4, 0, 1, 2 ] ], 1 ], - [ [ [ -6, 6, 4, -1, 0, 2 ], [ -5, 5, 4, 0, 0, 2 ], [ -6, 6, 4, 0, 0, 2 ], [ -7, 6, 5, 0, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 6, 4, -1, 0, 2 ], [ -5, 6, 3, 0, 0, 2 ], [ -6, 6, 4, 0, 0, 2 ], [ -7, 6, 5, 0, 0, 2 ] ], 1 ], - [ [ [ -6, 6, 4, -1, 0, 2 ], [ -5, 6, 3, 0, 0, 2 ], [ -6, 6, 4, 0, 0, 2 ], [ -7, 6, 4, 1, 0, 2 ] ], 1 ], - [ [ [ -6, 6, 3, 0, 0, 2 ], [ -5, 6, 3, 0, 0, 2 ], [ -6, 6, 4, 0, 0, 2 ], [ -7, 6, 4, 1, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 6, 3, 0, 0, 2 ], [ -5, 6, 3, 0, 0, 2 ], [ -5, 6, 2, 0, 0, 2 ], [ -7, 6, 4, 1, 0, 2 ] ], 1 ], - [ [ [ -6, 6, 3, 0, 0, 2 ], [ -5, 6, 3, 0, 0, 2 ], [ -5, 6, 2, 0, 0, 2 ], [ -6, 7, 3, 0, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 6, 3, 0, 0, 2 ], [ -5, 6, 2, -1, 0, 2 ], [ -5, 6, 2, 0, 0, 2 ], [ -6, 7, 3, 0, 0, 2 ] ], 1 ], - [ [ [ -6, 6, 2, 1, 0, 2 ], [ -5, 6, 2, -1, 0, 2 ], [ -5, 6, 2, 0, 0, 2 ], [ -6, 7, 3, 0, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 6, 2, 1, 0, 2 ], [ -5, 6, 2, -1, 0, 2 ], [ -6, 7, 2, 1, 0, 2 ], [ -6, 7, 3, 0, 0, 2 ] ], 1 ], - [ [ [ -6, 6, 2, 1, 0, 2 ], [ -7, 6, 2, 2, 0, 2 ], [ -6, 7, 2, 1, 0, 2 ], [ -6, 7, 3, 0, 0, 2 ] ], 1 ], - [ [ [ -6, 6, 2, 1, 0, 2 ], [ -7, 6, 2, 2, 0, 2 ], [ -6, 7, 2, 1, 0, 2 ], [ -5, 6, 2, 1, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 6, 2, 1, 0, 2 ], [ -7, 6, 2, 2, 0, 2 ], [ -5, 6, 2, 1, -1, 1 ], [ -5, 6, 2, 1, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 6, 2, 1, 0, 2 ], [ -7, 6, 2, 2, 0, 2 ], [ -6, 6, 2, 2, -1, 2 ], [ -5, 6, 2, 1, -1, 2 ] ], 1 ], - [ [ [ -6, 6, 2, 1, 0, 2 ], [ -7, 6, 2, 2, 0, 2 ], [ -6, 6, 2, 2, -1, 2 ], [ -7, 5, 2, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 6, 2, 1, 0, 2 ], [ -7, 6, 2, 2, 0, 2 ], [ -7, 5, 2, 3, 0, 2 ], [ -7, 5, 2, 2, 0, 2 ] ], 1 ], - [ [ [ -8, 6, 2, 2, 0, 2 ], [ -7, 6, 2, 2, 0, 2 ], [ -7, 5, 2, 3, 0, 2 ], [ -7, 5, 2, 2, 0, 2 ] ], 1 ], - [ [ [ -8, 6, 2, 2, 0, 2 ], [ -7, 5, 2, 2, -1, 2 ], [ -7, 5, 2, 3, 0, 2 ], [ -7, 5, 2, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 6, 2, 2, -1, 2 ], [ -7, 5, 2, 2, -1, 2 ], [ -7, 5, 2, 3, 0, 2 ], [ -7, 5, 2, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 6, 2, 2, -1, 2 ], [ -7, 5, 2, 2, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -7, 5, 2, 2, 0, 2 ] ], 1 ], - [ [ [ -7, 6, 2, 2, -1, 2 ], [ -6, 6, 2, 2, -2, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -7, 5, 2, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 6, 2, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -7, 5, 2, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 6, 2, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 2, 2, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 6, 2, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 6, 2, 2, -1, 2 ] ], 1 ], - [ [ [ -6, 5, 1, 2, 0, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 6, 2, 2, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 5, 1, 2, 0, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -5, 5, 0, 2, 0, 2 ], [ -6, 6, 2, 2, -1, 2 ] ], 1 ], - [ [ [ -6, 5, 1, 2, 0, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -5, 5, 0, 2, 0, 2 ], [ -6, 6, 1, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 5, 1, 2, 0, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -7, 6, 2, 2, 0, 2 ], [ -6, 6, 1, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 5, 1, 3, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -7, 6, 2, 2, 0, 2 ], [ -6, 6, 1, 2, 0, 2 ] ], 1 ], - [ [ [ -6, 5, 1, 3, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 5, 1, 2, -2, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 5, 1, 2, -2, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ] ], 1 ], - [ [ [ -7, 5, 1, 2, -2, 2 ], [ -7, 5, 1, 3, -2, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ] ], 1 ], - [ [ [ -7, 5, 1, 2, -1, 2 ], [ -7, 5, 1, 3, -2, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 5, 1, 2, -1, 2 ], [ -7, 5, 1, 3, -2, 2 ], [ -5, 5, 1, 1, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ] ], 1 ], - [ [ [ -6, 5, 1, 2, -2, 2 ], [ -7, 5, 1, 3, -2, 2 ], [ -5, 5, 1, 1, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ] ], 1 ], - [ [ [ -6, 5, 1, 2, -2, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -5, 5, 1, 1, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -8, 5, 0, 3, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -5, 5, 1, 1, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ] ], 1 ], - [ [ [ -8, 5, 0, 3, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 6, 1, 2, -2, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 6, 1, 2, -2, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -7, 6, 1, 3, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -8, 4, 1, 3, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -7, 6, 1, 3, -1, 2 ] ], 1 ], - [ [ [ -8, 4, 1, 3, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 1, 3, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -9, 5, 1, 4, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 1, 3, -1, 2 ] ], 1 ] - ], - [ - [ [ [ -9, 5, 1, 4, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 1, 4, -2, 2 ] ], 1 ], - [ [ [ -9, 5, 1, 4, -1, 2 ], [ -7, 5, 1, 4, -2, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 1, 4, -2, 2 ] ], 1 ] - ] - ] -], -"last_changes": -[ - [ [ -8, 4, 1, 3, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -7, 6, 1, 3, -1, 2 ] ], - [ [ -8, 4, 1, 3, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 1, 3, -1, 2 ] ], - [ [ -9, 5, 1, 4, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 1, 3, -1, 2 ] ], - [ [ -9, 5, 1, 4, -1, 2 ], [ -7, 5, 1, 3, -1, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 1, 4, -2, 2 ] ], - [ [ -9, 5, 1, 4, -1, 2 ], [ -7, 5, 1, 4, -2, 2 ], [ -6, 6, 1, 2, -1, 2 ], [ -6, 5, 1, 4, -2, 2 ] ] -], -"cur_uid": "7276dc78", -"ref_uid": "531df78c", -"order_seed": 350501, -"dur_seed": 664373, -"motifs_seed": 429600, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ 0, 1200, 0, 0, 0.069958847736626, 0, 0.31481481481481, 0, 0.38271604938272, 0.13068181818182, 0.45884773662551, 0.14772727272727, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.79218106995885, 0, 1, 0 ], -"passages_weights": [ 1, 0.47, 0.43, 1, 0.45 ], -"hd_exp": 3.87, -"hd_invert": 0, -"order": -[ - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 2 ], [ 1, 3, 0 ], [ ] ], - [ [ 0, 1 ], [ 2, 3 ], [ ] ], - [ [ 2, 3 ], [ 1, 0 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 0, 1 ], [ 2, 3 ], [ ] ], - [ [ 3 ], [ 2, 0, 1 ], [ ] ], - [ [ 1, 3, 2 ], [ 0 ], [ ] ], - [ [ 3, 0 ], [ 2, 1 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 1, 0 ], [ 2, 3 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 1, 3 ], [ 0, 2 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 2 ], [ 3, 1, 0 ], [ ] ], - [ [ 3 ], [ 2, 0, 1 ], [ ] ], - [ [ 1, 3 ], [ 0, 2 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 1, 2 ], [ 0, 3 ], [ ] ], - [ [ 3, 2, 1 ], [ 0 ], [ ] ], - [ [ 2, 0 ], [ 3, 1 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 25.244897959184, 25.244897959184 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/lilypond/part_I.ly deleted file mode 100644 index af7f26d..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/lilypond/part_I.ly +++ /dev/null @@ -1,48 +0,0 @@ -{ - { gis'1^\markup { \pad-markup #0.2 "-11"} } - \bar "|" - { fis1^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↑" }} } - \bar "|" - { c'1^\markup { \pad-markup #0.2 "+7"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }} ~ } - \bar "|" - { c'2 fis'2^\markup { \pad-markup #0.2 "-46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { fis'1 ~ } - \bar "|" - { fis'1 } - \bar "|" - { b'1^\markup { \pad-markup #0.2 "-17"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }} ~ } - \bar "|" - { b'2 g2^\markup { \pad-markup #0.2 "+1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g2 cis'2^\markup { \pad-markup #0.2 "+50"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} } - \bar "|" - { a'1^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { a'2 ais'2^\markup { \pad-markup #0.2 "+17"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 } - \bar "|" - { ais1^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais1 ~ } - \bar "|" - { ais2 d'2^\markup { \pad-markup #0.2 "+34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { d'2 g'2^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { g'2 b'2^\markup { \pad-markup #0.2 "+50"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/lilypond/part_II.ly deleted file mode 100644 index b3e65e4..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/lilypond/part_II.ly +++ /dev/null @@ -1,48 +0,0 @@ -{ - { d'1^\markup { \pad-markup #0.2 "+38"} ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'1 } - \bar "|" - { g'1^\markup { \pad-markup #0.2 "-35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { g'1 } - \bar "|" - { b'1^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { b'2 d'2^\markup { \pad-markup #0.2 "+42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↓" }} } - \bar "|" - { a'1^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↓" }} } - \bar "|" - { f'1^\markup { \pad-markup #0.2 "-30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }} ~ } - \bar "|" - { f'1 } - \bar "|" - { f'1^\markup { \pad-markup #0.2 "-35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 } - \bar "|" - { b'1^\markup { \pad-markup #0.2 "+28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} } - \bar "|" - { d'1^\markup { \pad-markup #0.2 "+3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }} } - \bar "|" - { g1^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g2 c'2^\markup { \pad-markup #0.2 "-5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }} ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'2 f'2^\markup { \pad-markup #0.2 "-35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }} ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/lilypond/part_III.ly deleted file mode 100644 index 192a5db..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/lilypond/part_III.ly +++ /dev/null @@ -1,48 +0,0 @@ -{ - { g'1^\markup { \pad-markup #0.2 "+36"} ~ } - \bar "|" - { g'2 b'2^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }} ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 } - \bar "|" - { a1^\markup { \pad-markup #0.2 "-3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }} ~ } - \bar "|" - { a2 d'2^\markup { \pad-markup #0.2 "+3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }} ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'1 } - \bar "|" - { cis1^\markup { \pad-markup #0.2 "+50"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }} ~ } - \bar "|" - { cis2 dis'2^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }} } - \bar "|" - { ais'1^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }} ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'2 d2^\markup { \pad-markup #0.2 "-19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }} ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d2 g2^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }} ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/lilypond/part_IV.ly deleted file mode 100644 index 5fd805f..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7276dc78/lilypond/part_IV.ly +++ /dev/null @@ -1,48 +0,0 @@ -{ - { ais,2^\markup { \pad-markup #0.2 "+21"} f2^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }} ~ } - \bar "|" - { f1 ~ } - \bar "|" - { f2 b2^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b2 e'2^\markup { \pad-markup #0.2 "+34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }} ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'2 d2^\markup { \pad-markup #0.2 "+3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { d2 a2^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a2 dis'2^\markup { \pad-markup #0.2 "+15"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↑" }} ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'2 g'2^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }} ~ } - \bar "|" - { g'2 e,2^\markup { \pad-markup #0.2 "+12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↓" }} ~ } - \bar "|" - { e,1 } - \bar "|" - { ais,1^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} } - \bar "|" - { e1^\markup { \pad-markup #0.2 "+12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }} } - \bar "|" - { dis,1^\markup { \pad-markup #0.2 "+46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }} } - \bar "|" - { b,1^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↓" }} } - \bar "|" - { c,1^\markup { \pad-markup #0.2 "+30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} } - \bar "|" - { f,1^\markup { \pad-markup #0.2 "+1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/78a94ed1_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/78a94ed1_code.scd deleted file mode 100644 index 42b64ff..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/78a94ed1_code.scd +++ /dev/null @@ -1,981 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - /* - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - */ - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - //lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - lastState = if(o == 0, {lastXChanges.last.deepCopy}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - /* - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - */ - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - //# voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - # voices, durs = seq.flatten2(if(oneShot, {2}, {3})).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(2).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/78a94ed1_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/78a94ed1_mus_model.json deleted file mode 100644 index 078670e..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/78a94ed1_mus_model.json +++ /dev/null @@ -1,90 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -6, 1, 5, 1, 0, 2 ], [ -5, 1, 4, 2, 0, 2 ], [ -5, 1, 5, 2, 0, 2 ], [ -4, 2, 5, 1, 0, 2 ] ], 1 ], - [ [ [ -6, 1, 5, 1, 0, 2 ], [ -5, 1, 4, 2, 0, 2 ], [ -3, 0, 5, 1, 0, 2 ], [ -4, 2, 5, 1, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 1, 5, 1, 0, 2 ], [ -5, 1, 4, 2, 0, 2 ], [ -3, 0, 5, 1, 0, 2 ], [ -4, 1, 5, 1, 0, 2 ] ], 1 ], - [ [ [ -6, 1, 5, 1, 0, 2 ], [ -5, 1, 4, 2, 0, 2 ], [ -4, 2, 5, 1, 0, 2 ], [ -4, 1, 5, 1, 0, 2 ] ], 1 ], - [ [ [ -6, 1, 5, 1, 0, 2 ], [ -5, 2, 5, 1, 0, 2 ], [ -4, 2, 5, 1, 0, 2 ], [ -4, 1, 5, 1, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 1, 5, 1, 0, 2 ], [ -5, 2, 5, 1, 0, 2 ], [ -5, 1, 6, 1, 0, 2 ], [ -4, 1, 5, 1, 0, 2 ] ], 1 ], - [ [ [ -6, 1, 5, 1, 0, 2 ], [ -4, 1, 4, 1, 0, 2 ], [ -5, 1, 6, 1, 0, 2 ], [ -4, 1, 5, 1, 0, 2 ] ], 1 ], - [ [ [ -6, 1, 5, 1, 0, 2 ], [ -4, 1, 4, 1, 0, 2 ], [ -5, 1, 6, 1, 0, 2 ], [ -4, 2, 5, 1, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 1, 5, 1, 0, 2 ], [ -4, 1, 4, 1, 0, 2 ], [ -5, 2, 5, 1, 0, 2 ], [ -4, 2, 5, 1, 0, 2 ] ], 1 ], - [ [ [ -6, 1, 5, 1, 0, 2 ], [ -4, 2, 4, 1, 0, 2 ], [ -5, 2, 5, 1, 0, 2 ], [ -4, 2, 5, 1, 0, 2 ] ], 1 ], - [ [ [ -7, 2, 5, 1, 1, 2 ], [ -4, 2, 4, 1, 0, 2 ], [ -5, 2, 5, 1, 0, 2 ], [ -4, 2, 5, 1, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 2, 5, 1, 1, 2 ], [ -4, 2, 4, 1, 0, 2 ], [ -5, 2, 5, 1, 0, 2 ], [ -5, 1, 5, 1, 1, 2 ] ], 1 ], - [ [ [ -7, 2, 5, 1, 1, 2 ], [ -4, 2, 4, 1, 0, 2 ], [ -4, 1, 4, 1, 0, 2 ], [ -5, 1, 5, 1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -7, 2, 5, 1, 1, 2 ], [ -4, 2, 4, 1, 0, 2 ], [ -4, 1, 4, 1, 0, 2 ], [ -3, 1, 4, 0, 0, 2 ] ], 1 ], - [ [ [ -6, 2, 5, 1, 0, 2 ], [ -4, 2, 4, 1, 0, 2 ], [ -4, 1, 4, 1, 0, 2 ], [ -3, 1, 4, 0, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 2, 4, 1, 1, 2 ], [ -4, 2, 4, 1, 0, 2 ], [ -4, 1, 4, 1, 0, 2 ], [ -3, 1, 4, 0, 0, 2 ] ], 1 ], - [ [ [ -6, 2, 4, 1, 1, 2 ], [ -4, 2, 4, 1, 0, 2 ], [ -4, 1, 4, 1, 0, 2 ], [ -3, 2, 4, 0, 0, 2 ] ], 1 ], - [ [ [ -6, 2, 4, 1, 1, 2 ], [ -4, 2, 4, 1, 0, 2 ], [ -5, 3, 4, 1, 0, 2 ], [ -3, 2, 4, 0, 0, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 2, 4, 1, 1, 2 ], [ -4, 2, 4, 1, 0, 2 ], [ -5, 3, 4, 1, 0, 2 ], [ -5, 2, 4, 2, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 2, 4, 1, 1, 2 ], [ -4, 2, 4, 1, 0, 2 ], [ -5, 3, 4, 1, 0, 2 ], [ -6, 2, 4, 2, 1, 2 ] ], 1 ], - [ [ [ -6, 2, 4, 1, 1, 2 ], [ -5, 3, 4, 1, 1, 2 ], [ -5, 3, 4, 1, 0, 2 ], [ -6, 2, 4, 2, 1, 2 ] ], 1 ], - [ [ [ -6, 2, 4, 1, 1, 2 ], [ -5, 3, 4, 1, 1, 2 ], [ -5, 2, 4, 1, 1, 3 ], [ -6, 2, 4, 2, 1, 2 ] ], 1 ] - ], - [ - [ [ [ -6, 2, 4, 1, 1, 2 ], [ -5, 3, 4, 1, 1, 2 ], [ -5, 2, 4, 2, 1, 2 ], [ -6, 2, 4, 2, 1, 2 ] ], 1 ], - [ [ [ -6, 2, 4, 1, 1, 2 ], [ -5, 3, 4, 1, 1, 2 ], [ -5, 2, 4, 2, 1, 2 ], [ -6, 3, 4, 2, 1, 2 ] ], 1 ] - ] - ] -], -"last_changes": -[ - [ [ -6, 2, 4, 1, 1, 2 ], [ -4, 2, 4, 1, 0, 2 ], [ -5, 3, 4, 1, 0, 2 ], [ -6, 2, 4, 2, 1, 2 ] ], - [ [ -6, 2, 4, 1, 1, 2 ], [ -5, 3, 4, 1, 1, 2 ], [ -5, 3, 4, 1, 0, 2 ], [ -6, 2, 4, 2, 1, 2 ] ], - [ [ -6, 2, 4, 1, 1, 2 ], [ -5, 3, 4, 1, 1, 2 ], [ -5, 2, 4, 1, 1, 3 ], [ -6, 2, 4, 2, 1, 2 ] ], - [ [ -6, 2, 4, 1, 1, 2 ], [ -5, 3, 4, 1, 1, 2 ], [ -5, 2, 4, 2, 1, 2 ], [ -6, 2, 4, 2, 1, 2 ] ], - [ [ -6, 2, 4, 1, 1, 2 ], [ -5, 3, 4, 1, 1, 2 ], [ -5, 2, 4, 2, 1, 2 ], [ -6, 3, 4, 2, 1, 2 ] ] -], -"cur_uid": "78a94ed1", -"ref_uid": "4e9f1dcc", -"order_seed": 418736, -"dur_seed": 167372, -"motifs_seed": 741164, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ 0, 1200, 0.0061728395061728, 0.10227272727273, 0.074074074074074, 0.10227272727273, 0.2037037037037, 0.090909090909091, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.7880658436214, 0.034090909090909, 1, 0.034090909090909 ], -"passages_weights": [ 1, 0.47, 0.43, 1, 0.2 ], -"hd_exp": 2, -"hd_invert": 0, -"order": -[ - [ [ 1, 0 ], [ 3, 2 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ], - [ [ 0, 1 ], [ 3, 2 ], [ ] ], - [ [ 1, 2 ], [ 3, 0 ], [ ] ], - [ [ 1 ], [ 0, 3, 2 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 0 ], [ 3, 1, 2 ], [ ] ], - [ [ 0, 1 ], [ 2, 3 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 10.091836734694, 10.091836734694 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/lilypond/part_I.ly deleted file mode 100644 index cf060ff..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/lilypond/part_I.ly +++ /dev/null @@ -1,26 +0,0 @@ -{ - { c''1^\markup { \pad-markup #0.2 "-15"} } - \bar "|" - { f'1^\markup { \pad-markup #0.2 "-17"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'2 c''2^\markup { \pad-markup #0.2 "-15"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''2 ais2^\markup { \pad-markup #0.2 "+35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { ais2 dis'2^\markup { \pad-markup #0.2 "+28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↓" }} ~ } - \bar "|" - { dis'1 } - \bar "|" - { ais'1^\markup { \pad-markup #0.2 "+30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }} } - \bar "|" - { b'2^\markup { \pad-markup #0.2 "+19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }} b2^\markup { \pad-markup #0.2 "+19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }} ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b2 fis'2^\markup { \pad-markup #0.2 "+21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/lilypond/part_II.ly deleted file mode 100644 index 9712ce1..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/lilypond/part_II.ly +++ /dev/null @@ -1,26 +0,0 @@ -{ - { dis'2^\markup { \pad-markup #0.2 "-48"} ais'2^\markup { \pad-markup #0.2 "-19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { ais'2 c''2^\markup { \pad-markup #0.2 "-15"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { c''2 a2^\markup { \pad-markup #0.2 "-30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { a1 } - \bar "|" - { c'1^\markup { \pad-markup #0.2 "-15"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { c'1 } - \bar "|" - { cis'1^\markup { \pad-markup #0.2 "-3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'2 dis'2^\markup { \pad-markup #0.2 "+1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'2 ais'2^\markup { \pad-markup #0.2 "-9"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }} } - \bar "|" - { b'1^\markup { \pad-markup #0.2 "+19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/lilypond/part_III.ly deleted file mode 100644 index 4950731..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/lilypond/part_III.ly +++ /dev/null @@ -1,26 +0,0 @@ -{ - { b1^\markup { \pad-markup #0.2 "-34"} ~ } - \bar "|" - { b1 } - \bar "|" - { c'1^\markup { \pad-markup #0.2 "-15"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} } - \bar "|" - { cis'1^\markup { \pad-markup #0.2 "-3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { cis'2 gis'2^\markup { \pad-markup #0.2 "-1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }} ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 } - \bar "|" - { a'1^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { a'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/lilypond/part_IV.ly deleted file mode 100644 index f5a6564..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/78a94ed1/lilypond/part_IV.ly +++ /dev/null @@ -1,26 +0,0 @@ -{ - { f,1^\markup { \pad-markup #0.2 "-17"} ~ } - \bar "|" - { f,1 ~ } - \bar "|" - { f,1 ~ } - \bar "|" - { f,1 ~ } - \bar "|" - { f,1 } - \bar "|" - { f,1^\markup { \pad-markup #0.2 "+37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↑" }} ~ } - \bar "|" - { f,1 } - \bar "|" - { c2^\markup { \pad-markup #0.2 "-15"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }} d2^\markup { \pad-markup #0.2 "-50"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↑" }} ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/7c30c182_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/7c30c182_code.scd deleted file mode 100644 index 42b64ff..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/7c30c182_code.scd +++ /dev/null @@ -1,981 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - /* - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - */ - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - //lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - lastState = if(o == 0, {lastXChanges.last.deepCopy}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - /* - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - */ - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - //# voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - # voices, durs = seq.flatten2(if(oneShot, {2}, {3})).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(2).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/7c30c182_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/7c30c182_mus_model.json deleted file mode 100644 index f796261..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/7c30c182_mus_model.json +++ /dev/null @@ -1,271 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 1 ], - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ -1, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, -1, -1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, -1, -1, 0, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 0, -1, 0, -1, 0 ], [ 1, -1, -1, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 0, -1, 0, -1, 0 ], [ 1, -1, -1, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 0, 0, -1, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 0, -1, 0, -1, 0 ], [ 1, -1, -1, 0, 0, 0 ], [ 2, 0, -1, 0, -2, 0 ], [ 0, 0, -1, 1, 0, 0 ] ], 1 ], - [ [ [ 0, 0, -1, 0, -1, 0 ], [ 1, 0, -1, 0, -1, 0 ], [ 2, 0, -1, 0, -2, 0 ], [ 0, 0, -1, 1, 0, 0 ] ], 1 ], - [ [ [ 0, 0, -1, 0, -1, 0 ], [ 1, 0, -1, 0, -1, 0 ], [ 2, 0, -1, 0, -2, 0 ], [ 2, -1, -1, 0, -1, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 0, -1, 0, -1, 0 ], [ 1, 0, -1, 0, -1, 0 ], [ 2, 0, -2, 0, -1, 0 ], [ 2, -1, -1, 0, -1, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 0, -2, 0, 0, 0 ], [ 1, 0, -1, 0, -1, 0 ], [ 2, 0, -2, 0, -1, 0 ], [ 2, -1, -1, 0, -1, 0 ] ], 1 ], - [ [ [ 0, 0, -2, 0, 0, 0 ], [ 2, -1, -2, 0, -1, 0 ], [ 2, 0, -2, 0, -1, 0 ], [ 2, -1, -1, 0, -1, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 0, -2, 0, 0, 0 ], [ 2, -1, -2, 0, -1, 0 ], [ 3, -1, -3, 0, -1, 0 ], [ 2, -1, -1, 0, -1, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 0, -2, 0, 0, 0 ], [ 1, 0, -2, 0, 1, 0 ], [ 3, -1, -3, 0, -1, 0 ], [ 2, -1, -1, 0, -1, 0 ] ], 1 ], - [ [ [ 0, 0, -2, 0, 0, 0 ], [ 1, 0, -2, 0, 1, 0 ], [ 3, -1, -3, 0, -1, 0 ], [ 2, -1, -2, 0, 0, 0 ] ], 1 ], - [ [ [ 0, 0, -2, 0, 0, 0 ], [ 1, 0, -2, 0, 1, 0 ], [ 0, 0, -2, 1, 0, 0 ], [ 2, -1, -2, 0, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 0, -2, 0, 0, 0 ], [ 1, 0, -2, 0, 1, 0 ], [ 0, 0, -2, 1, 0, 0 ], [ 1, 0, -3, 1, 0, 0 ] ], 1 ], - [ [ [ 0, 0, -3, 0, 1, 0 ], [ 1, 0, -2, 0, 1, 0 ], [ 0, 0, -2, 1, 0, 0 ], [ 1, 0, -3, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 0, -3, 0, 1, 0 ], [ 2, -1, -3, 0, 1, 0 ], [ 0, 0, -2, 1, 0, 0 ], [ 1, 0, -3, 1, 0, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 0, -3, 0, 1, 0 ], [ 2, -1, -3, 0, 1, 0 ], [ 0, 0, -3, 1, 1, 0 ], [ 1, 0, -3, 1, 0, 0 ] ], 1 ], - [ [ [ 0, 0, -3, 0, 1, 0 ], [ 2, -1, -3, 0, 1, 0 ], [ 0, 0, -3, 1, 1, 0 ], [ 1, 0, -3, 0, 2, 0 ] ], 1 ], - [ [ [ 0, 0, -3, 0, 1, 0 ], [ 0, 0, -2, 0, 1, 0 ], [ 0, 0, -3, 1, 1, 0 ], [ 1, 0, -3, 0, 2, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 0, -3, 0, 1, 0 ], [ 0, 0, -2, 0, 1, 0 ], [ 0, 0, -3, 1, 1, 0 ], [ 1, 0, -3, 0, 1, 0 ] ], 1 ], - [ [ [ 0, 0, -3, 0, 1, 0 ], [ 0, 0, -2, 0, 1, 0 ], [ 1, 0, -3, 0, 2, 0 ], [ 1, 0, -3, 0, 1, 0 ] ], 1 ], - [ [ [ 0, 0, -3, 0, 1, 0 ], [ 1, -1, -3, 0, 1, 0 ], [ 1, 0, -3, 0, 2, 0 ], [ 1, 0, -3, 0, 1, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 0, -3, 0, 1, 0 ], [ 1, -1, -3, 0, 1, 0 ], [ 2, -1, -3, 0, 1, 0 ], [ 1, 0, -3, 0, 1, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 0, -3, 0, 1, 0 ], [ 1, -1, -3, 0, 1, 0 ], [ 2, -1, -3, 0, 1, 0 ], [ 2, -1, -4, 0, 1, 0 ] ], 1 ], - [ [ [ 0, 0, -3, 0, 1, 0 ], [ 1, -1, -3, 0, 1, 0 ], [ 1, -1, -3, 1, 1, 0 ], [ 2, -1, -4, 0, 1, 0 ] ], 1 ] - ], - [ - [ [ [ 0, 0, -3, 0, 1, 0 ], [ 2, -2, -4, 0, 1, 0 ], [ 1, -1, -3, 1, 1, 0 ], [ 2, -1, -4, 0, 1, 0 ] ], 1 ] - ], - [ - [ [ [ 1, -1, -4, 0, 1, 0 ], [ 2, -2, -4, 0, 1, 0 ], [ 1, -1, -3, 1, 1, 0 ], [ 2, -1, -4, 0, 1, 0 ] ], 1 ], - [ [ [ 1, -1, -4, 0, 1, 0 ], [ 1, -2, -3, 1, 1, 0 ], [ 1, -1, -3, 1, 1, 0 ], [ 2, -1, -4, 0, 1, 0 ] ], 1 ] - ], - [ - [ [ [ 1, -1, -4, 0, 1, 0 ], [ 2, -1, -5, 0, 1, 0 ], [ 1, -1, -3, 1, 1, 0 ], [ 2, -1, -4, 0, 1, 0 ] ], 1 ] - ], - [ - [ [ [ 1, -1, -4, 0, 1, 0 ], [ 2, -1, -5, 0, 1, 0 ], [ 1, -1, -3, 1, 1, 0 ], [ 2, -1, -5, 0, 2, 0 ] ], 1 ], - [ [ [ 1, -1, -4, 0, 1, 0 ], [ 2, -1, -5, 0, 1, 0 ], [ 3, -1, -5, 0, 0, 0 ], [ 2, -1, -5, 0, 2, 0 ] ], 1 ] - ], - [ - [ [ [ 2, -2, -5, 0, 1, 0 ], [ 2, -1, -5, 0, 1, 0 ], [ 3, -1, -5, 0, 0, 0 ], [ 2, -1, -5, 0, 2, 0 ] ], 1 ] - ], - [ - [ [ [ 2, -2, -5, 0, 1, 0 ], [ 2, -1, -5, 0, 1, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 2, -1, -5, 0, 2, 0 ] ], 1 ], - [ [ [ 2, -2, -5, 0, 1, 0 ], [ 2, -1, -6, 0, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 2, -1, -5, 0, 2, 0 ] ], 1 ], - [ [ [ -1, -1, -5, 0, 3, 0 ], [ 2, -1, -6, 0, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 2, -1, -5, 0, 2, 0 ] ], 1 ] - ], - [ - [ [ [ -1, -1, -5, 0, 3, 0 ], [ 2, -1, -6, 0, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 1, 0, -5, -1, 2, 0 ] ], 1 ], - [ [ [ 1, -2, -5, -1, 2, 0 ], [ 2, -1, -6, 0, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 1, 0, -5, -1, 2, 0 ] ], 1 ], - [ [ [ 1, -2, -5, -1, 2, 0 ], [ 2, 0, -5, -1, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 1, 0, -5, -1, 2, 0 ] ], 1 ] - ], - [ - [ [ [ 1, -1, -5, -1, 1, 0 ], [ 2, 0, -5, -1, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 1, 0, -5, -1, 2, 0 ] ], 1 ] - ], - [ - [ [ [ 1, -1, -5, -1, 1, 0 ], [ 2, 0, -5, -1, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 1, -1, -5, -1, 2, 1 ] ], 1 ] - ], - [ - [ [ [ 1, -1, -5, -1, 1, 0 ], [ 3, -1, -6, -1, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 1, -1, -5, -1, 2, 1 ] ], 1 ], - [ [ [ 1, -1, -6, -1, 2, 0 ], [ 3, -1, -6, -1, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 1, -1, -5, -1, 2, 1 ] ], 1 ] - ], - [ - [ [ [ 0, -1, -5, 0, 2, 0 ], [ 3, -1, -6, -1, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 1, -1, -5, -1, 2, 1 ] ], 1 ], - [ [ [ 0, -1, -5, 0, 2, 0 ], [ 2, -1, -5, 0, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 1, -1, -5, -1, 2, 1 ] ], 1 ] - ], - [ - [ [ [ 0, -1, -5, 0, 2, 0 ], [ 2, -1, -5, 0, 2, 0 ], [ 2, -2, -5, -1, 2, 1 ], [ 1, -1, -5, -1, 2, 1 ] ], 1 ], - [ [ [ 0, -1, -5, 0, 2, 0 ], [ 3, -1, -5, -2, 2, 1 ], [ 2, -2, -5, -1, 2, 1 ], [ 1, -1, -5, -1, 2, 1 ] ], 1 ] - ], - [ - [ [ [ 0, -1, -5, 0, 2, 0 ], [ 3, -1, -5, -2, 2, 1 ], [ 2, -1, -5, -1, 1, 1 ], [ 1, -1, -5, -1, 2, 1 ] ], 1 ], - [ [ [ 0, -1, -5, 0, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 2, -1, -5, -1, 1, 1 ], [ 1, -1, -5, -1, 2, 1 ] ], 1 ] - ], - [ - [ [ [ 0, -1, -5, 0, 2, 0 ], [ 2, -1, -5, 0, 1, 1 ], [ 2, -1, -5, -1, 1, 1 ], [ 1, -1, -5, -1, 2, 1 ] ], 1 ], - [ [ [ 0, -1, -5, 0, 2, 0 ], [ 2, -1, -5, 0, 1, 1 ], [ 2, -1, -5, -1, 1, 1 ], [ 2, -1, -5, -1, 0, 1 ] ], 1 ] - ], - [ - [ [ [ 0, -1, -5, 0, 2, 0 ], [ 3, -1, -6, -1, 1, 1 ], [ 2, -1, -5, -1, 1, 1 ], [ 2, -1, -5, -1, 0, 1 ] ], 1 ] - ], - [ - [ [ [ 0, -1, -5, 0, 2, 0 ], [ 3, -1, -6, -1, 1, 1 ], [ 2, -1, -5, -1, 1, 1 ], [ 2, -1, -6, -1, 1, 1 ] ], 1 ] - ], - [ - [ [ [ 0, -1, -5, 0, 2, 0 ], [ 3, -1, -6, -1, 1, 1 ], [ 3, -2, -6, -1, 1, 1 ], [ 2, -1, -6, -1, 1, 1 ] ], 1 ], - [ [ [ 0, -1, -5, 0, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 3, -2, -6, -1, 1, 1 ], [ 2, -1, -6, -1, 1, 1 ] ], 1 ] - ], - [ - [ [ [ 0, -1, -5, 0, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 3, -2, -6, -1, 1, 1 ], [ 2, -2, -6, -1, 1, 2 ] ], 1 ] - ], - [ - [ [ [ 1, 0, -5, -1, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 3, -2, -6, -1, 1, 1 ], [ 2, -2, -6, -1, 1, 2 ] ], 1 ], - [ [ [ 1, 0, -5, -1, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 3, -2, -6, -1, 1, 1 ], [ 3, -2, -5, -1, 2, 0 ] ], 1 ], - [ [ [ 1, 0, -5, -1, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 2, -1, -5, -1, 3, 0 ], [ 3, -2, -5, -1, 2, 0 ] ], 1 ] - ], - [ - [ [ [ 1, 0, -5, -1, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 2, 0, -5, -1, 2, 0 ], [ 3, -2, -5, -1, 2, 0 ] ], 1 ] - ], - [ - [ [ [ 2, -1, -6, -1, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 2, 0, -5, -1, 2, 0 ], [ 3, -2, -5, -1, 2, 0 ] ], 1 ], - [ [ [ 2, -1, -6, -1, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 2, 0, -5, -1, 2, 0 ], [ 3, -1, -5, -1, 1, 0 ] ], 1 ], - [ [ [ 2, -1, -6, -1, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 3, -1, -6, -1, 2, 0 ], [ 3, -1, -5, -1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ 2, -1, -6, -1, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 2, -1, -5, 0, 2, 0 ], [ 3, -1, -5, -1, 1, 0 ] ], 1 ], - [ [ [ 1, -1, -5, 0, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 2, -1, -5, 0, 2, 0 ], [ 3, -1, -5, -1, 1, 0 ] ], 1 ], - [ [ [ 1, -1, -5, 0, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 2, -1, -5, 0, 2, 0 ], [ 3, -1, -6, -1, 2, 0 ] ], 1 ] - ], - [ - [ [ [ 3, -1, -6, -2, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 2, -1, -5, 0, 2, 0 ], [ 3, -1, -6, -1, 2, 0 ] ], 1 ] - ], - [ - [ [ [ 3, -1, -6, -2, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 2, -1, -5, 0, 2, 0 ], [ 4, -1, -6, -2, 2, -1 ] ], 1 ], - [ [ [ 3, -1, -6, -2, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 4, -1, -6, -2, 2, 0 ], [ 4, -1, -6, -2, 2, -1 ] ], 1 ] - ], - [ - [ [ [ 3, -1, -6, -2, 2, 0 ], [ 3, -1, -5, -1, 2, 0 ], [ 4, -1, -6, -2, 2, 0 ], [ 4, -2, -6, -2, 2, 0 ] ], 1 ] - ], - [ - [ [ [ 3, -1, -6, -2, 2, 0 ], [ 5, -1, -6, -3, 2, 0 ], [ 4, -1, -6, -2, 2, 0 ], [ 4, -2, -6, -2, 2, 0 ] ], 1 ], - [ [ [ 3, -1, -6, -2, 2, 0 ], [ 5, -1, -6, -3, 2, 0 ], [ 5, -2, -7, -2, 2, 0 ], [ 4, -2, -6, -2, 2, 0 ] ], 1 ] - ], - [ - [ [ [ 4, -2, -7, -2, 2, 0 ], [ 5, -1, -6, -3, 2, 0 ], [ 5, -2, -7, -2, 2, 0 ], [ 4, -2, -6, -2, 2, 0 ] ], 1 ] - ], - [ - [ [ [ 4, -2, -7, -2, 2, 0 ], [ 5, -1, -6, -3, 2, 0 ], [ 5, -2, -7, -2, 2, 0 ], [ 5, -3, -7, -2, 2, 0 ] ], 1 ], - [ [ [ 4, -1, -6, -3, 2, 0 ], [ 5, -1, -6, -3, 2, 0 ], [ 5, -2, -7, -2, 2, 0 ], [ 5, -3, -7, -2, 2, 0 ] ], 1 ] - ], - [ - [ [ [ 4, -3, -7, -1, 2, 0 ], [ 5, -1, -6, -3, 2, 0 ], [ 5, -2, -7, -2, 2, 0 ], [ 5, -3, -7, -2, 2, 0 ] ], 1 ], - [ [ [ 4, -3, -7, -1, 2, 0 ], [ 5, -1, -6, -3, 2, 0 ], [ 5, -3, -7, -2, 2, 1 ], [ 5, -3, -7, -2, 2, 0 ] ], 1 ] - ], - [ - [ [ [ 4, -3, -7, -1, 2, 0 ], [ 5, -1, -6, -3, 2, 0 ], [ 4, -1, -6, -2, 2, 0 ], [ 5, -3, -7, -2, 2, 0 ] ], 1 ] - ], - [ - [ [ [ 4, -2, -6, -2, 2, 0 ], [ 5, -1, -6, -3, 2, 0 ], [ 4, -1, -6, -2, 2, 0 ], [ 5, -3, -7, -2, 2, 0 ] ], 1 ], - [ [ [ 4, -2, -6, -2, 2, 0 ], [ 5, -1, -6, -3, 2, 0 ], [ 4, -1, -6, -2, 2, 0 ], [ 3, 0, -6, -2, 2, 0 ] ], 1 ], - [ [ [ 4, -2, -6, -2, 2, 0 ], [ 3, -2, -6, -2, 2, 0 ], [ 4, -1, -6, -2, 2, 0 ], [ 3, 0, -6, -2, 2, 0 ] ], 1 ] - ], - [ - [ [ [ 4, -2, -6, -2, 2, 0 ], [ 3, -2, -6, -2, 2, 0 ], [ 4, -1, -6, -2, 2, 0 ], [ 3, -1, -6, -2, 2, 1 ] ], 1 ], - [ [ [ 4, -2, -6, -2, 2, 0 ], [ 3, -1, -6, -2, 1, 0 ], [ 4, -1, -6, -2, 2, 0 ], [ 3, -1, -6, -2, 2, 1 ] ], 1 ], - [ [ [ 4, -1, -6, -2, 1, 0 ], [ 3, -1, -6, -2, 1, 0 ], [ 4, -1, -6, -2, 2, 0 ], [ 3, -1, -6, -2, 2, 1 ] ], 1 ] - ], - [ - [ [ [ 4, -1, -7, -2, 2, 0 ], [ 3, -1, -6, -2, 1, 0 ], [ 4, -1, -6, -2, 2, 0 ], [ 3, -1, -6, -2, 2, 1 ] ], 1 ] - ] - ] -], -"last_changes": -[ - [ [ 4, -2, -6, -2, 2, 0 ], [ 3, -2, -6, -2, 2, 0 ], [ 4, -1, -6, -2, 2, 0 ], [ 3, 0, -6, -2, 2, 0 ] ], - [ [ 4, -2, -6, -2, 2, 0 ], [ 3, -2, -6, -2, 2, 0 ], [ 4, -1, -6, -2, 2, 0 ], [ 3, -1, -6, -2, 2, 1 ] ], - [ [ 4, -2, -6, -2, 2, 0 ], [ 3, -1, -6, -2, 1, 0 ], [ 4, -1, -6, -2, 2, 0 ], [ 3, -1, -6, -2, 2, 1 ] ], - [ [ 4, -1, -6, -2, 1, 0 ], [ 3, -1, -6, -2, 1, 0 ], [ 4, -1, -6, -2, 2, 0 ], [ 3, -1, -6, -2, 2, 1 ] ], - [ [ 4, -1, -7, -2, 2, 0 ], [ 3, -1, -6, -2, 1, 0 ], [ 4, -1, -6, -2, 2, 0 ], [ 3, -1, -6, -2, 2, 1 ] ] -], -"cur_uid": "7c30c182", -"ref_uid": "nil", -"order_seed": 993548, -"dur_seed": 828564, -"motifs_seed": 174746, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ -1200, 1200, 0, 0, 0.037037037037037, 0, 0.18518518518519, 0, 0.45679012345679, 0, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58230452674897, 0, 0.61111111111111, 0, 0.7798353909465, 0, 1, 0 ], -"passages_weights": [ 1, 0.47, 0.43, 1, 1 ], -"hd_exp": 3.22, -"hd_invert": 0, -"order": -[ - [ [ 1, 3 ], [ 0, 2 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 0 ], [ 2, 1, 3 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 3, 1, 0 ], [ 2 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 0 ], [ 2, 3, 1 ], [ ] ], - [ [ 0 ], [ 3, 2, 1 ], [ ] ], - [ [ 1, 3, 0 ], [ 2 ], [ ] ], - [ [ 1, 0 ], [ 3, 2 ], [ ] ], - [ [ 0, 2, 3 ], [ 1 ], [ ] ], - [ [ 3, 2 ], [ 0, 1 ], [ ] ], - [ [ 2, 3, 0 ], [ 1 ], [ ] ], - [ [ 1, 0 ], [ 3, 2 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ], - [ [ 2 ], [ 3, 0, 1 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 2, 3 ], [ 1, 0 ], [ ] ], - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 3, 0 ], [ 2, 1 ], [ ] ], - [ [ 3, 0 ], [ 2, 1 ], [ ] ], - [ [ 0, 2 ], [ 1, 3 ], [ ] ], - [ [ 3, 0, 2 ], [ 1 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 0, 3 ], [ 2, 1 ], [ ] ], - [ [ 1, 2, 0 ], [ 3 ], [ ] ], - [ [ 1 ], [ 0, 3, 2 ], [ ] ], - [ [ 3, 0, 1 ], [ 2 ], [ ] ], - [ [ 1 ], [ 0, 3, 2 ], [ ] ], - [ [ 1 ], [ 2, 0, 3 ], [ ] ], - [ [ 2, 1, 3 ], [ 0 ], [ ] ], - [ [ 0, 1 ], [ 3, 2 ], [ ] ], - [ [ 0, 2, 1 ], [ 3 ], [ ] ], - [ [ 3, 0 ], [ 1, 2 ], [ ] ], - [ [ 3, 1, 2 ], [ 0 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 1, 3 ], [ 0, 2 ], [ ] ], - [ [ 1, 0, 3 ], [ 2 ], [ ] ], - [ [ 2 ], [ 0, 3, 1 ], [ ] ], - [ [ 2 ], [ 3, 1, 0 ], [ ] ], - [ [ 2, 3, 1 ], [ 0 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 48.479591836735, 48.479591836735 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/lilypond/part_I.ly deleted file mode 100644 index 533c6b9..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/lilypond/part_I.ly +++ /dev/null @@ -1,92 +0,0 @@ -{ - { c'1^\markup { \pad-markup #0.2 "+0"} } - \bar "|" - { e'1^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { e'2 f'2^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'2 fis'2^\markup { \pad-markup #0.2 "-17"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }} ~ } - \bar "|" - { fis'1 } - \bar "|" - { gis'1^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 } - \bar "|" - { a'1^\markup { \pad-markup #0.2 "+25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} } - \bar "|" - { ais'1^\markup { \pad-markup #0.2 "+10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }} ~ } - \bar "|" - { ais'1 } - \bar "|" - { b'1^\markup { \pad-markup #0.2 "+44"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }} } - \bar "|" - { fis'1^\markup { \pad-markup #0.2 "-8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { fis'1 } - \bar "|" - { g'1^\markup { \pad-markup #0.2 "+4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }} ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 } - \bar "|" - { a'1^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↑" }} ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'1 } - \bar "|" - { fis1^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }} ~ } - \bar "|" - { fis1 } - \bar "|" - { g1^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }} ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 } - \bar "|" - { gis1^\markup { \pad-markup #0.2 "+38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↓" }} } - \bar "|" - { ais1^\markup { \pad-markup #0.2 "+3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { ais2 b2^\markup { \pad-markup #0.2 "+42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }} ~ } - \bar "|" - { b2 e'2^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'2 f'2^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↓" }} ~ } - \bar "|" - { f'1 ~ } - \bar "|" - { f'2 g'2^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }} ~ } - \bar "|" - { g'2 cis'2^\markup { \pad-markup #0.2 "+5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }} ~ } - \bar "|" - { cis'2 d'2^\markup { \pad-markup #0.2 "+43"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'2 e'2^\markup { \pad-markup #0.2 "-45"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'2 e'2^\markup { \pad-markup #0.2 "+47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }} ~ } - \bar "|" - { e'2 fis'2^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }} ~ } - \bar "|" - { fis'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/lilypond/part_II.ly deleted file mode 100644 index c4d9581..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/lilypond/part_II.ly +++ /dev/null @@ -1,92 +0,0 @@ -{ - { c'2^\markup { \pad-markup #0.2 "+0"} g'2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { g'2 gis'2^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 ~ } - \bar "|" - { gis'1 } - \bar "|" - { a'1^\markup { \pad-markup #0.2 "+11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }} ~ } - \bar "|" - { a'2 b'2^\markup { \pad-markup #0.2 "-24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { b'1 } - \bar "|" - { c''1^\markup { \pad-markup #0.2 "-12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }} ~ } - \bar "|" - { c''2 d'2^\markup { \pad-markup #0.2 "-4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }} ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'2 e'2^\markup { \pad-markup #0.2 "-39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }} ~ } - \bar "|" - { e'1 ~ } - \bar "|" - { e'2 b'2^\markup { \pad-markup #0.2 "+44"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }} ~ } - \bar "|" - { b'2 b'2^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { b'2 a'2^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }} ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'2 ais'2^\markup { \pad-markup #0.2 "-34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↓" }} ~ } - \bar "|" - { ais'2 b'2^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↓" }} ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'2 c'2^\markup { \pad-markup #0.2 "+39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }} ~ } - \bar "|" - { c'2 d'2^\markup { \pad-markup #0.2 "-11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }} ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'2 dis'2^\markup { \pad-markup #0.2 "+1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 } - \bar "|" - { f'2^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↑" }} fis'2^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { fis'1 } - \bar "|" - { g'2^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} a'2^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }} ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'1 } - \bar "|" - { a'1^\markup { \pad-markup #0.2 "+45"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { a'2 b'2^\markup { \pad-markup #0.2 "-43"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }} ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 } - \bar "|" - { c''2^\markup { \pad-markup #0.2 "-5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }} a'2^\markup { \pad-markup #0.2 "+45"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }} ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'1 ~ } - \bar "|" - { a'1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/lilypond/part_III.ly deleted file mode 100644 index 2a0ff52..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/lilypond/part_III.ly +++ /dev/null @@ -1,92 +0,0 @@ -{ - { c'1^\markup { \pad-markup #0.2 "+0"} ~ } - \bar "|" - { c'1 } - \bar "|" - { c''1^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { c''2 cis'2^\markup { \pad-markup #0.2 "+12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { cis'1 ~ } - \bar "|" - { cis'2 dis'2^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'2 e'2^\markup { \pad-markup #0.2 "-26"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }} ~ } - \bar "|" - { e'2 ais'2^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }} ~ } - \bar "|" - { ais'1 ~ } - \bar "|" - { ais'1 } - \bar "|" - { b'1^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { b'2 ais2^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { ais1 } - \bar "|" - { b1^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} ~ } - \bar "|" - { b1 } - \bar "|" - { c'1^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }} } - \bar "|" - { d'2^\markup { \pad-markup #0.2 "-43"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }} dis'2^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }} ~ } - \bar "|" - { dis'1 ~ } - \bar "|" - { dis'1 } - \bar "|" - { f'1^\markup { \pad-markup #0.2 "-17"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }} ~ } - \bar "|" - { f'1 } - \bar "|" - { fis'1^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { fis'2 g'2^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }} ~ } - \bar "|" - { g'1 } - \bar "|" - { a'1^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} } - \bar "|" - { ais'1^\markup { \pad-markup #0.2 "-28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↓" }} } - \bar "|" - { b'2^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }} c''2^\markup { \pad-markup #0.2 "-42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }} ~ } - \bar "|" - { c''2 ais'2^\markup { \pad-markup #0.2 "+3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 5↓" }} ~ } - \bar "|" - { ais'1 } - \bar "|" - { b'1^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }} ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 ~ } - \bar "|" - { b'1 } - \bar "|" - { c''1^\markup { \pad-markup #0.2 "-24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }} ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''1 ~ } - \bar "|" - { c''1 } - \bar "|" - { d1^\markup { \pad-markup #0.2 "+43"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} } - \bar "|" - { e1^\markup { \pad-markup #0.2 "-6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↓" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/lilypond/part_IV.ly deleted file mode 100644 index 3a4f61a..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7c30c182/lilypond/part_IV.ly +++ /dev/null @@ -1,92 +0,0 @@ -{ - { c1^\markup { \pad-markup #0.2 "+0"} ~ } - \bar "|" - { c1 ~ } - \bar "|" - { c1 } - \bar "|" - { cis1^\markup { \pad-markup #0.2 "+12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }} } - \bar "|" - { dis1^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↓" }} ~ } - \bar "|" - { dis1 ~ } - \bar "|" - { dis1 } - \bar "|" - { e1^\markup { \pad-markup #0.2 "+27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↑" }} ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e1 ~ } - \bar "|" - { e2 fis2^\markup { \pad-markup #0.2 "-8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }} ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis1 ~ } - \bar "|" - { fis2 g2^\markup { \pad-markup #0.2 "+4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { g1 ~ } - \bar "|" - { g1 } - \bar "|" - { gis1^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } - \bar "|" - { gis2 d,2^\markup { \pad-markup #0.2 "+20"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }} ~ } - \bar "|" - { d,2 e,2^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }} ~ } - \bar "|" - { e,2 f,2^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 11↓" }} ~ } - \bar "|" - { f,1 } - \bar "|" - { g,2^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} a,2^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }} ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 ~ } - \bar "|" - { a,1 } - \bar "|" - { fis1^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }} ~ } - \bar "|" - { fis1 } - \bar "|" - { g1^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }} ~ } - \bar "|" - { g1 } - \bar "|" - { a1^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} } - \bar "|" - { a1^\markup { \pad-markup #0.2 "+45"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↓" }} ~ } - \bar "|" - { a1 ~ } - \bar "|" - { a1 } - \bar "|" - { b1^\markup { \pad-markup #0.2 "-43"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} } - \bar "|" - { c'2^\markup { \pad-markup #0.2 "-24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} cis'2^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }} ~ } - \bar "|" - { cis'1 } - \bar "|" - { d'1^\markup { \pad-markup #0.2 "+43"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }} ~ } - \bar "|" - { d'1 ~ } - \bar "|" - { d'2 e'2^\markup { \pad-markup #0.2 "-6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/7ede7adb_code.scd b/resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/7ede7adb_code.scd deleted file mode 100644 index 42b64ff..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/7ede7adb_code.scd +++ /dev/null @@ -1,981 +0,0 @@ -( -// helper funcs -var hsArrayToCents, pDist, hdSum, hsChordalDistance, hsArrayToFreq; - -// score funcs -var isInRange, spacingScore, rangeScore, intervalScore, inclusionScore; - -// subroutines -var genTuples, initVoices, genOrders, genSubMotif, updateVoices, genDurFunc, genStepFunc; - -// primary routines -var genMotif, genSecondarySeq; - -// audition funcs -var genPatterns, genMidiPatterns; - -// resource management funcs -var seedFunc, genUID, writeResources, stringifyToDepth, setSeeds, sanityCheck, -msgInterpret, loadLedgerFile, loadLedgerJSON, loadModelFile, loadModelJSON, -setGlobalVars, globalVarsToDict, saveLedger; - -// model vars -//(model and global vars mostly set by OSC funcs -var seq, lastXChanges, -curUID, refUID, orderSeed, durSeed, motifSeed, -entrancesProbVals, passagesProbVals, exitsProbVals, -ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, -orders, susWeights, orderSize, passagesSize, -motifEdited, orderEdited; - -// model aux vars -var entrancesDurFunc, passagesDurFunc, exitsDurFunc, stepFunc; - -// other global vars -var popSize, exPath, dir, primes, dims, tuples, -group, player, resourceDir, ledgerPath, ledger, currentlyPlayingUID, -nameSpaces; - -// install JSON quark (not used) -/* -if(Quarks.isInstalled("JSONlib").not, { - Quarks.install("https://github.com/musikinformatik/JSONlib.git"); - thisProcess.recompile; - //HelpBrowser.openHelpFor("Classes/JSONlib"); -}); -*/ - - -//------helper funcs - -hsArrayToCents = { - arg hsArray; - hsArray.collect({arg dist, p; dist * 1200 * log2(primes[p][0]/primes[p][1])}).sum -}; - -pDist = { - arg array1, array2, signed = false; - var pDistance; - pDistance = hsArrayToCents.value(array2) - hsArrayToCents.value(array1); - if(signed, {pDistance}, {abs(pDistance)}) -}; - -hdSum = { - arg hsArrays; - var size, distances, mean; - size = hsArrays.size; - distances = (size - 1).collect({arg i; - ((i + 1)..(size - 1)).collect({arg j; - abs(hsArrays[i] - hsArrays[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsChordalDistance = { - arg hsArrays1, hsArrays2; - var size, distances, mean; - size = hsArrays1.size; - distances = hsArrays1.size.collect({arg i; - hsArrays2.size.collect({arg j; - abs(hsArrays1[i] - hsArrays2[j]).collect({arg dist, p; dist * log2(primes[p].product)}).sum - }); - }).flat; - mean = distances.sum / distances.size; - distances.sum - //mean + ((1 / sqrt((pow(distances - mean, 2)).sum / distances.size)) * mean) -}; - -hsArrayToFreq = { - arg array; - array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product -}; - -//------score funcs - -/* -isInRange = { - arg hsArray, min, max; - var cents; - cents = hsArrayToCents.value(hsArray); - (cents >= min) && (cents <= max) -}; -*/ - -spacingScore = { - arg hsArrays, min; - var centsArray; - centsArray = hsArrays.collect({arg hsArray; hsArrayToCents.value(hsArray)}).sort({arg a, b; a < b}); - centsArray.differentiate.drop(1).collect({arg pDistance; if(pDistance >= min, {1}, {0.01})}).sum; -}; - -rangeScore = { - arg hsArray1, hsArray2, min, max, low, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - if((pDistance >= min) && (pDistance <= max), {1}, {low}); -}; - -/* -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = false; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - stepFunc.value(pDistance) -}; -*/ - -intervalScore = { - arg hsArray1, hsArray2, mean, sd, signed = true; - var pDistance; - pDistance = pDist.value(hsArray1, hsArray2, signed); - //pDistance.gaussCurve(1, mean, sd) - //if(pDistance >= 0, {stepFunc.value(abs(pDistance))}, {0.01}); - stepFunc.value(pDistance) -}; - -inclusionScore = { - arg array, test, min = 0.01; - if(array.collect({arg v; v.hash}).includes(test.hash), {min}, {1}); -}; - - -//------subroutines - -genTuples = { - var tuples; - tuples = dims.collect({[-1, 0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum <= 1) && (tuple[0] == 0)}); - //tuples = dims.collect({[0, 1]}).allTuples.select({arg tuple; (abs(tuple.drop(1)).sum == 1) && (tuple[0] == 0)}); - tuples = tuples ++ tuples.collect({arg tuple; [-3, -2, -1, 1, 2, 3].collect({arg octTrans; tuple.deepCopy.put(0, octTrans)})}).flatten; -}; - -initVoices = { - var init, voicesInit; - voicesInit = popSize.collect({dims.collect({0})}); - /* - voicesInit = [dims.collect({0})]; - (popSize - 1).do({ - arg rep, new; - rep = dims.rand; - new = voicesInit.last.deepCopy; - new[rep] = new[rep] + [-1, 1].choose(); - voicesInit = voicesInit.add(new); - }); - */ - voicesInit.deepCopy; -}; - -genDurFunc = {arg chordProb, minPad, maxPad, minDur, maxDur, envData, seed; - var env, pTable, durFunc; - env = Env.pairs([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).asSignal(256).asList.asArray; - pTable = env.asRandomTable; - [chordProb, minPad, maxPad, minDur, maxDur, envData].postln; - durFunc = {arg allowChord, pad = false; - var res; - res = if(allowChord.not, { - pTable.tableRand * (maxDur - minDur) + minDur - }, { - if(1.0.rand < chordProb, {0}, {pTable.tableRand * (maxDur - minDur) + minDur}); - }).round(0.125); - if(pad, {res = res + rrand(minPad.asFloat, maxPad.asFloat).round(0.125)}); - if(res.asInteger == res, {res = res.asInteger}); - res - }; - seedFunc.value(durFunc, seed); -}; - -genStepFunc = {arg minStep, maxStep, envData, seed; - var envDataNorm, env, pTable, stepFunc; - [minStep, maxStep, envData].postln; - envDataNorm = ([[0, 0]] ++ envData.clump(2) ++ [[1, 0]]).flop; - envDataNorm = [envDataNorm[0].normalize(minStep, maxStep), envDataNorm[1]].flop; - env = Env.pairs(envDataNorm); - stepFunc = {arg pDist; - env.at(pDist).clip(0.001, 1); - }; - seedFunc.value(stepFunc, seed); -}; - -genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5; - ((maxMotifLength.asInteger - minMotifLength.asInteger).rand + minMotifLength.asInteger).collect({ - var noProgIns, noSusIns, noSilentIns, prog, sus, silent, order; - noSusIns = [1, 2, 3].wchoose(susWeights.normalizeSum); - //noProgIns = (popSize - noSusIns).rand + 1; - noProgIns = (popSize - noSusIns); - noSilentIns = popSize - noSusIns - noProgIns; - - # prog, sus, silent = (0..(popSize-1)).scramble.clumps([noProgIns, noSusIns, noSilentIns]); - - prog = (prog.scramble ++ ((maxProgLength.asInteger - minProgLength.asInteger).rand + minProgLength.asInteger).collect({prog.choose}).scramble); - if(silent == nil, {silent = []}); - [sus.scramble, prog, silent.scramble] - }); -}; - -updateVoices = {arg ins, sus; - var voices, candidates, nWeights, nProbs, sel; - - voices = lastXChanges.deepCopy.last; - - candidates = sus.collect({arg v; tuples.collect({arg t; voices[v] + t})}).flatten; - candidates = difference(candidates.asSet, voices.asSet).asList; - nProbs = candidates.collect({arg candidate; - var stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore; - - //stepScore = intervalScore.value(voices[ins], candidate, 30, 400, 0.1); - stepScore = intervalScore.value(voices[ins], candidate, 100, 100); - recentlySoundedScore = inclusionScore.value(lastXChanges.flop[ins], candidate, 0.01); - - - - /* - if(rangeScore.value(candidate.collect({0}), voices[ins], ranges[ins][1] - 500, ranges[ins][1], 0, true) == 1, { - isInRangeScore = 1 - rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0] + 500, ranges[ins][1] - 500, 0, true); - isInRangeScore = isInRangeScore * rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true) - }, { - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - }); - */ - - - isInRangeScore = rangeScore.value(candidate.collect({0}), candidate, ranges[ins][0], ranges[ins][1], 0, true); - //old way - worked but actually by accident (I think) - //isInRangeScore = rangeScore.value(candidate, candidate.collect({0}), ranges[ins][0], ranges[ins][1], 0, true); - - - regScore = spacingScore.value(voices.deepCopy.put(ins, candidate), 300); - hdScore = pow(hdSum.value(voices.deepCopy.put(ins, candidate)), hdExp); - if(hdInvert == 0, {hdScore = 1/hdScore}); - //maybe what you want here is a vector to another root and then favoring movement towards it. - //distScore = pow(hsChordalDistance.value(voices, voices.put(ins, candidate)), 2); - - [stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore] - }); - - nWeights = passagesWeights; - - //this handles nWeights of 0; mainly for testing - nProbs = nProbs.flop.select({arg scores, s; nWeights[s] != 0}).flop; - nWeights = nWeights.select({arg weight; weight != 0}); - nProbs = nProbs.flop.collect({arg scores, s; - if(scores.sum == 0, {scores}, {scores.normalizeSum * nWeights[s]}) - }); - nProbs = nProbs.flop.collect({arg scores, s; scores.product}).normalizeSum; - - sel = candidates.wchoose(nProbs); - - voices[ins] = sel; - lastXChanges = lastXChanges.add(voices).keep(-5); -}; - -genSubMotif = {arg order, orderIndex, lastState, repeatLast = false, startFromLast = false, isLastOrder = false; - var sus, prog, silent, flatOrder, res, isInChord, allowChord, pad, lastXChangesHold, voices, adder; - # sus, prog, silent = order; - flatOrder = silent ++ sus ++ prog; - lastXChangesHold = lastXChanges.deepCopy; - voices = lastState.deepCopy; - isInChord = popSize.collect({false}); - allowChord = false; - pad = false; - res = []; - "------generating motif".postln; - //need to figure out here if voices move between motifs - flatOrder.do({arg ins, i; - - if(prog.includes(ins) && repeatLast.not, {updateVoices.value(ins, sus)}); - adder = if(silent.includes(ins), {["Rest"]}, {lastXChanges.last.deepCopy[ins]}); - - if(voices[ins] != adder, { - var dur; - - if((sus ++ silent).includes(ins), { - allowChord = (ins != sus.last); - pad = (ins == sus.last); - }, { - if(i < (flatOrder.size - 1), { - allowChord = (isInChord[flatOrder[i + 1]] || (ins == flatOrder[i + 1])).not; - pad = false; - }, { - allowChord = false; - pad = true - }); - }); - if((orderIndex == 0) && sus.includes(ins), { - dur = entrancesDurFunc.value(allowChord, pad); - }, { - dur = passagesDurFunc.value(allowChord, pad); - }); - if(dur == 0, {isInChord[ins] = true}, {isInChord = popSize.collect({false})}); - - voices[ins] = adder; - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - - // pad ending - /* - if(orderIndex == (orders.size - 1), { - (0..(popSize-1)).scramble.do({arg ins; - if(res.last.first[ins] != ["Rest"], { - var dur; - voices[ins] = ["Rest"]; - allowChord = (voices != popSize.collect({["Rest"]})); - pad = allowChord.not; - dur = exitsDurFunc.value(allowChord, pad); - res = res.add([voices.deepCopy.postln, dur]); - }); - }); - }); - */ - - //format and return - if(startFromLast, {lastXChanges = lastXChangesHold.deepCopy}); - res; -}; - - -//------primary routines - -genMotif = { - var repeats, fSeq, fDur, durAdd; - - repeats = 1; - fSeq = []; - - repeats.do({arg index; - var motif; - - motif = []; - - orders.do({arg order, o; - var lastState, subMotif; - //lastState = if(o == 0, {popSize.collect({["Rest"]})}, {motif.last.last.first}); - lastState = if(o == 0, {lastXChanges.last.deepCopy}, {motif.last.last.first}); - subMotif = genSubMotif.value(order, o, lastState, isLastOrder: o == (orders.size - 1)); - motif = motif.add(subMotif); - - }); - - sanityCheck.value(motif, index); - - fSeq = fSeq.add(motif); - }); - - //round last duration to measure - /* - fDur = fSeq.flatten.flatten.slice(nil, 1).sum; - durAdd = fDur.round(4) - fDur; - if(durAdd < 0, {durAdd = 4 - durAdd}); - fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] = fSeq[0][orders.size - 1][fSeq[0][orders.size - 1].size - 1][1] + durAdd; - */ - - fSeq -}; - -genSecondarySeq = {arg seq; - var curdles, fSeq; - curdles = []; - while({curdles.sum < seq.size}, {curdles = curdles ++ [3.rand + 1]}); - - fSeq = seq.clumps(curdles).collect({arg clump, m; - var repeats, paddedSeq; - - //add rest - paddedSeq = clump.add([[[popSize.collect({["Rest"]}), 0.5.rand]]]); - - //implement repeats - repeats = [0.rand + 1, 1].wchoose([1, 0].normalizeSum); - repeats.collect({paddedSeq}); - }); - fSeq -}; - - -//------audition funcs - -/* -Event.addEventType(\osc, { - if (~addr.postln.notNil) { - ~addr.sendMsg(~indexPath, ~indexMsg); - ~addr.sendMsg(~seqPath, stringifyToDepth.value(~seqMsg, 3)); - //~addr.sendMsg("/STATE/OPEN", (dir.replace("supercollider", "resources") +/+ ~idMsg +/+ ~idMsg ++ "_gui_state" ++ ".state").standardizePath.postln); - }; -}); -*/ - -Event.addEventType(\osc, { - if (~addr.notNil) { - ~msg; - ~addr.sendMsg(~path, *~msg); - }; -}); - -genPatterns = {arg inSeq, addr, oneShot = false; - var voices, durs, pbinds, res, indices, sectionDurs, msg, ids, seq; - seq = inSeq.collect({arg mSeq; mSeq[0]}); - //# voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - # voices, durs = seq.flatten2(if(oneShot, {2}, {3})).flop; - pbinds = voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs, attacks, rels, amps; - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - //attacks = 2.collect({rrand(1, 3)}) ++ freqs.drop(2).collect({rrand(0.3, 0.5)}); - attacks = fDurs.collect({arg dur; dur * rrand(0.2, 0.4)}); - //rels = freqs.drop(2).collect({rrand(0.3, 0.5)}) ++ 2.collect({rrand(1, 3)}); - rels = (clumps.size - 1).collect({arg c; - if(clumps[c + 1][0] == ["Rest"], {rrand(1.0, 3.0)}, {rrand(0.3, 0.5)}); - }); - rels = rels.add(rrand(1.0, 3.0)); - amps = freqs.collect({rrand(0.6, 0.99)}); - - [ - Pbind( - \instrument, \string_model, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \attack, Pseq(attacks, 1), - \sustain, Pseq(fDurs, 1), - \release, Pseq(rels, 1), - //\amp, Pseq(amps, 1), - \amp, Pbrown(0.5, 1, 0.5), - \busIndex, v - ), - Pbind( - \instrument, \sine, - \group, group, - \freq, Pseq(freqs, 1), - \dur, Pseq(fDurs, 1), - \sustain, Pseq(fDurs, 1), - \busIndex, v - ) - ] - }).flatten; - if(oneShot.not, { - msg = inSeq.collect({arg mSeq, m; mSeq[1..]}); - //ids = inSeq.collect({arg mSeq, m; mSeq[2]}); - sectionDurs = seq.collect({arg mSeq; mSeq.flatten2(2).flop[1].sum}); - pbinds = pbinds ++ - [ - Pbind( - \type, \osc, - \addr, addr, - \path, "/playing", - \msg, Pseq(msg, 1), - \dur, Pseq(sectionDurs, 1) - ); - ] - }); - res = Ppar(pbinds); - res -}; - -/* -genMidiPatterns = {arg seq; - var voices, durs, patterns, res, mOut, pbRange; - pbRange = 1; //semitones - change this as needed for your situation - mOut = MIDIOut.newByName("TiMidity", "TiMidity port 0").latency_(Server.default.latency); - # voices, durs = seq.flatten2(seq.maxDepth - 5).flop; - res = Ppar( - voices.flop.collect({arg voice, v; - var clumps, hdScores, freqs, fDurs; - - mOut.program(v, 70); - - clumps = voice.separate({arg a, b; a != b }); - freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))}, {Rest(0)})}); - fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum}); - - Pbind( - \type, \midi, - \chan, v, - \noteval, Pseq(freqs.cpsmidi - 24, 1), - \note, Pfunc({ | event | event[\noteval].floor }), - \dur, Pseq(fDurs, 1), - \midiout, mOut, - \amp, 1, - \bend, Pfunc({ - | event | - if (event[\note].isRest.not) { - var pitchbendvalue = event[\noteval].frac.linlin(0, pbRange, 8192, 8192*2).asInteger; - m.bend(v, pitchbendvalue); - }; - 0; // return something other than nil to avoid stopping the pattern - }), - ); - }); - ); - res -}; -*/ - - -//------resource management funcs - -genUID = {Date.seed.asHexString.toLower}; - -seedFunc = {arg func, seed; - var funcArgs, next; - next = Routine({loop{func.valueArray(funcArgs).yield }}); - next.randSeed_(seed); - {arg ...args; funcArgs = args; next.value} -}; - -stringifyToDepth = {arg data, maxDepth = 1; - var prettyString = "", rCount = 0, writeArray, indent; - - if(maxDepth == 0, { - data.asCompileString - }, { - indent = {arg size; size.collect({" "}).join("")}; - writeArray = {arg array; - prettyString = prettyString ++ indent.value(rCount) ++ "[\n"; - rCount = rCount + 1; - if(rCount < maxDepth, { - array.do({arg subArray; writeArray.value(subArray)}); - }, { - prettyString = prettyString ++ array.collect({arg subArray; - indent.value(rCount + 1) ++ subArray.asCompileString - }).join(",\n"); - }); - rCount = rCount - 1; - prettyString = prettyString ++ "\n" ++ indent.value(rCount) ++ "],\n"; - }; - - writeArray.value(data); - prettyString.replace(",\n\n", "\n").drop(-2); - }) -}; - -sanityCheck = {arg motif, index; - //print functions = very helpful - ("----------" + index + "------------").postln; - - motif.flatten.do({arg val, v; - if(v > 0, { - if(motif.flatten[v-1][0].hammingDistance(val[0]) > 1, {"problem 1".postln}); - if(motif.flatten[v-1][0].hammingDistance(val[0]) == 0, {"problem 2".postln}); - }); - val.postln - }); - "***********".postln; -}; - -msgInterpret = {arg in, escapeDoubleQuotes = true, escapeSingleQuotes = true; - var res; - - res = in; - if(res.isNil.not, { - if((res.isArray && res.isString.not), { - res = res.asCompileString; - res = res.replace(" ", "").replace("\n", "").replace("\t", ""); - if(escapeSingleQuotes, {res = res.replace("\'", "")}); - if(escapeDoubleQuotes, {res = res.replace("\"", "")}); - res = res.replace("Rest", "\"Rest\""); - res = res.interpret; - }, { - var tmpRes; - if(res.every({arg char; char.isDecDigit}), {tmpRes = res.asInteger}); - if(res.contains("."), {tmpRes = res.asFloat}); - if(tmpRes != nil, {res = tmpRes}); - }); - }); - res -}; - -writeResources = {arg path, dict; - var file, modelItems, resString; - file = File(path,"w"); - - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - - resString = nameSpaces.collect({arg nameSpace; - var depth = 0, insert = " "; - if(nameSpace == "music_data", {depth = 3; insert = "\n"}); - if(nameSpace == "last_changes", {depth = 1; insert = "\n"}); - if(nameSpace == "order", {depth = 1; insert = "\n"}); - if((nameSpace == "ref_uid") && (dict[nameSpace] == nil), {dict[nameSpace] = "nil"}); - "\"" ++ nameSpace ++ "\":" ++ insert ++ stringifyToDepth.value(dict[nameSpace], depth) - }).join(",\n"); - - resString = "{\n" ++ resString ++ "\n}"; - - file.write(resString); - file.close; - resString -}; - -loadModelFile = {arg path; loadModelJSON.value(File(path, "r").readAllString.parseJSON)}; - -loadModelJSON = {arg jsonObject; - var dict; - dict = Dictionary.with(*nameSpaces.collect({arg nS; nS->msgInterpret.value(jsonObject[nS])})); - dict -}; - -setGlobalVars = {arg dict, skipLastXChanges = false; - var tmpLastXChanges; - tmpLastXChanges = lastXChanges.deepCopy; - // order really matters!!!! - # seq, lastXChanges, curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited = nameSpaces.collect({arg nS; dict[nS]}); - if(skipLastXChanges, {lastXChanges = tmpLastXChanges}); - dict -}; - -globalVarsToDict = { - var modelItems, dict; - // order really matters!!!! - modelItems = [ - seq, lastXChanges, - curUID, refUID, orderSeed, durSeed, motifSeed, - entrancesProbVals, passagesProbVals, exitsProbVals, - ranges, stepProbsVals, passagesWeights, hdExp, hdInvert, - orders, susWeights, orderSize, passagesSize, - motifEdited, orderEdited - ]; - dict = Dictionary.with(*nameSpaces.collect({arg nS, n; nS->modelItems[n]})); -}; - -loadLedgerFile = {arg path; - ledgerPath = path; - resourceDir = path.splitext(".").drop(-1).join; - loadLedgerJSON.value(File(ledgerPath, "r").readAllString.parseJSON) -}; - -loadLedgerJSON = {arg jsonObject; ledger = jsonObject["ledger"]}; - -saveLedger = {arg ledger, path; - var file, curResourceDir; - file = File(path, "w"); - curResourceDir = resourceDir; - resourceDir = path.splitext(".").drop(-1).join; - if(curResourceDir != resourceDir, { - File.mkdir(resourceDir); - ledger.do({arg id; - File.copy(curResourceDir +/+ id, resourceDir +/+ id); - }); - }); - file.write("{\n\"ledger\":\n" ++ stringifyToDepth.value(ledger, 1) ++ "\n}"); - file.close; -}; - -//------global vars - -primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]]; -//ranges = [[-2400, 0], [-1200, 1200], [0, 2400], [0, 2400]]; -exPath = thisProcess.nowExecutingPath; -dir = exPath.dirname; -//popSize = 4; -dims = primes.size; -tuples = genTuples.value(); -//refUID = nil; -group = Group.new; -~group = group; -loadLedgerFile.value(dir +/+ ".." +/+ "resources" +/+ "piece_ledger.json"); -resourceDir = (dir +/+ ".." +/+ "resources" +/+ "piece_ledger"); -//passagesWeights = [1, 1, 1, 1, 1]; -//susWeights = [1, 1, 1]; -// order really matters!!!! -nameSpaces = [ - "music_data", "last_changes", "cur_uid", "ref_uid", "order_seed", "dur_seed", "motifs_seed", - "entrances_probs_vals","passages_probs_vals", "exits_probs_vals", - "ranges", "step_probs_vals", "passages_weights", "hd_exp", "hd_invert", - "order", "sus_weights", "order_size", "passages_size", - "motif_edited", "order_edited" -]; - - -//------OSC funcs - -OSCdef(\load_ledger, {arg msg, time, addr, port; - loadLedgerFile.value(msg[1].asString); -}, \load_ledger); - -OSCdef(\load_model, {arg msg, time, addr, port; - var dict; - dict = loadModelFile.value(msg[1].asString); - setGlobalVars.value(dict); -}, \load_model); - -OSCdef(\save_ledger, {arg msg, time, addr, port; - msg.postln; - ledger = msgInterpret.value(msg[1].asString.parseJSON["ledger"], false).postln; - //loadLedgerJSON.value(msg[0]) - saveLedger.value(ledger, msg[2].asString); - //loadLedgerFile.value(msg[1].asString); -}, \save_ledger); - -OSCdef(\generate, {arg msg, time, addr, port; - var path, dict, durSeeds, musPath, modelString; - msg.postln; - - path = msg[1].asString; - - dict = loadModelFile.value(path); - setGlobalVars.value(dict, true); - - popSize = ranges.size; - - //refUID.postln; - - loadLedgerFile.value(ledgerPath); - if(ledger == nil, {ledger = ["tmp"]}); - if(ledger.last != "tmp", {ledger = ledger.add("tmp")}); - - if(refUID == nil, {lastXChanges = [initVoices.value().deepCopy]}); - if((refUID != nil) && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - lastXChanges = msgInterpret.value(file.readAllString.parseJSON["last_changes"]); - }); - - refUID.postln; - lastXChanges.collect({arg item; item.postln}); - - durSeeds = seedFunc.value({3.collect({rrand(100000, 999999)})}, durSeed).value.postln; - entrancesDurFunc = genDurFunc.valueArray(entrancesProbVals[..4] ++ [entrancesProbVals[5..]] ++ [durSeeds[0]]); - passagesDurFunc = genDurFunc.valueArray(passagesProbVals[..4] ++ [passagesProbVals[5..]] ++ [durSeeds[1]]); - exitsDurFunc = genDurFunc.valueArray(exitsProbVals[..4] ++ [exitsProbVals[5..]] ++ [durSeeds[2]]); - - if(orders == nil, { - orders = seedFunc.value(genOrders, orderSeed).valueArray(orderSize ++ passagesSize); - //addr.sendMsg("/order", stringifyToDepth.value(orders, 1)); - }); - - stepFunc = genStepFunc.valueArray(stepProbsVals[..1] ++ [stepProbsVals[2..]] ++ [motifSeed]); - seq = seedFunc.value(genMotif, motifSeed).value; - - lastXChanges.collect({arg item; item.postln}); - - dict = globalVarsToDict.value; - modelString = writeResources.value(path, dict); - - //addr.sendMsg("/generated", musPath, stringifyToDepth.value(seq, 3)); - //~seq = seq; - - addr.sendMsg("/generated", path, modelString, ledgerPath); -}, \generate); - - -OSCdef(\commit, {arg msg, time, addr, port; - var musicData, musicChanged, dict, newLedger, modelPath, musString, musFile, test1, test2, lastCurUID, commitType, commitPos, equalityLedger; - //msg.postln; - - /* - test1 = msg[1].asString.parseJSON; - test2 = (dir +/+ ".." +/+ "resources/tmp/tmp_music" ++ ".json").standardizePath.parseJSONFile; - msgInterpret.value(test1["music"])[0][0][0][1].class.postln; - msgInterpret.value(test2["music_data"])[0][0][0][1].class.postln; - (test1["music"] == test2["music_data"]).postln; - */ - - musicData = loadModelJSON.value(msg[1].asString.parseJSON)["music_data"].postln; - musicChanged = (musicData != seq).postln; - commitType = msg[2].asString; - commitPos = msg[3].postln.asInteger; - - lastCurUID = curUID.deepCopy; - curUID = genUID.value; - - File.mkdir((resourceDir +/+ curUID).standardizePath); - File.copy(exPath, (resourceDir +/+ curUID +/+ curUID ++ "_code" ++ ".scd").standardizePath); - - modelPath = (resourceDir +/+ curUID +/+ curUID ++ "_mus_model" ++ ".json").standardizePath; - dict = globalVarsToDict.value; - if(musicChanged, { - seq = musicData; - dict["music_data"] = seq; - dict["motif_edited"] = "true" - }); - dict["cur_uid"] = curUID; - - writeResources.value(modelPath, dict); - - File.delete(ledgerPath ++ "_bak"); - File.copy(ledgerPath, ledgerPath ++ "_bak"); - File.delete(ledgerPath); - - /* - if(commitType == "add", { - if(lastCurUID == "tmp", { - ledger = ledger.drop(-1).add(curUID); - }, { - ledger = ledger.add(curUID); - }) - }); - */ - - ledger.postln; - - if(commitType == "add", {ledger = ledger.add(curUID)}); - - if(commitType == "insert", {ledger = ledger.insert(commitPos + 1, curUID)}); - - if(commitType == "replace", {ledger = ledger.put(commitPos, curUID)}); - - equalityLedger = ledger.collect({arg item; item.asSymbol}); - if(equalityLedger.includes(\tmp).postln, {ledger.removeAt(equalityLedger.indexOf(\tmp).postln)}); - - ledger.postln; - - saveLedger.value(ledger, ledgerPath); - - addr.sendMsg("/committed", curUID, ledgerPath); - //refUID = curUID; - -}, \commit); - -OSCdef(\transport, {arg msg, time, addr, port; - msg.postln; - if(msg[1] == 0, { - group.set(\release, 2); - group.set(\gate, 0); - player.stop; - }, { - // the cued sequence can now be read from file, so this can be cleaned up - var cSize, patterns, pSeq, cuedSeek, indexStart, indexEnd, tmpLedger; - if(msg[1] == 1, { - pSeq = []; - cuedSeek = (seq != nil); - indexStart = msg[2].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.postln.parseJSON["music_data"]), path, indexStart + index, uid]); - file.close; - }); - }); - if(cuedSeek, { - var path, file; - path = (resourceDir +/+ "tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - patterns = genPatterns.value(pSeq, addr); - }, { - pSeq = [loadModelJSON.value(msg[2].asString.parseJSON)["music_data"].postln]; - patterns = genPatterns.value(pSeq, addr, true); - }); - player = Pfset(pattern: patterns, cleanupFunc: { - addr.sendMsg("/transport", 0); - addr.sendMsg("/one_shot", 0); - }); - player = player.play - }); -}, \transport); - - -OSCdef(\transcribe_motif, {arg msg, time, addr, port; - var tSeq, refChord, refUID; - - msg.postln; - - tSeq = [loadModelJSON.value(msg[1].asString.parseJSON)["music_data"]]; - refUID = msg[2].asString.postln; - - if((refUID != "nil") && (refUID != "tmp"), { - var file; - file = File((resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }, { - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - }); - - ~transcribe.value(tSeq, refChord, (dir +/+ ".." +/+ "lilypond" +/+ "includes").standardizePath, addr, "/transcribe_motif"); -}, \transcribe_motif); - - -OSCdef(\transcribe_all, {arg msg, time, addr, port; - var cSize, patterns, cuedSeek, indexStart, indexEnd, tmpLedger; - if(true, { - cuedSeek = (seq != nil); - indexStart = msg[1].asInteger; - indexEnd = ledger.size - if(cuedSeek, {2}, {1}); - - //tmp for testing transcription - //indexEnd = (indexStart+5); - - //ledger.postln; - if(((indexStart == (ledger.size - 1)) && cuedSeek).not, { - var lilyPartLedgerFiles; - - lilyPartLedgerFiles = 4.collect({arg p; - File((dir +/+ ".." +/+ "lilypond" +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath, "w"); - }); - - ledger[indexStart..indexEnd].do({arg uid, index; - var path, file, fileString, tSeq, refUID, refChord; - path = (resourceDir +/+ uid +/+ uid ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - fileString = file.readAllString; - tSeq = msgInterpret.value(fileString.parseJSON["music_data"]); - refUID = msgInterpret.value(fileString.parseJSON["ref_uid"]); - file.close; - - //uid.postln; - //(refUID == "nil").postln; - - refChord = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]; - - if(refUID != "nil", { - path = (resourceDir +/+ refUID +/+ refUID ++ "_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - refChord = msgInterpret.value(file.readAllString.parseJSON["last_changes"]).last; - file.close; - }); - - if(index != indexEnd, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath); - }, { - ~transcribe.value(tSeq, refChord, (resourceDir +/+ uid +/+ "lilypond").standardizePath, addr, "/transcribe_all"); - }); - - lilyPartLedgerFiles.do({arg f, p; - f.write("\\include \"" ++ resourceDir +/+ uid +/+ "lilypond" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly\"\n"); - }); - - }); - - lilyPartLedgerFiles.do({arg f; - f.close - }); - }); - /* - if(cuedSeek, { - var path, file; - path = (dir +/+ ".." +/+ "resources/tmp/tmp_mus_model" ++ ".json").standardizePath; - file = File(path, "r"); - pSeq = pSeq.add([msgInterpret.value(file.readAllString.parseJSON["music_data"]), path, ledger.size - 1, "tmp"]); - file.close; - }); - */ - }, { - - }); - -}, \transcribe_all); - -) - - diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/7ede7adb_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/7ede7adb_mus_model.json deleted file mode 100644 index b5aa312..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/7ede7adb_mus_model.json +++ /dev/null @@ -1,83 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ -4, 2, 2, 3, 1, 0 ], [ -5, 3, 2, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -4, 2, 2, 3, 1, 0 ], [ -3, 1, 1, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 1, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 1, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -3, 2, 2, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -2, 1, 1, 2, 1, 0 ], [ -3, 1, 1, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -5, 2, 1, 2, 1, 0 ], [ -3, 1, 1, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -4, 2, 1, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 2, 1, 2, 1, 0 ], [ -3, 1, 1, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -4, 3, 1, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 2, 1, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -4, 3, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -5, 3, 1, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -4, 3, 1, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 3, 1, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -3, 1, 2, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 3, 1, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -4, 3, 2, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 3, 1, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ], [ -4, 2, 2, 2, 1, 0 ], [ -2, 2, 1, 1, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 3, 1, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ], [ -4, 3, 2, 2, 1, 0 ], [ -2, 2, 1, 1, 1, 0 ] ], 1 ], - [ [ [ -5, 3, 1, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ], [ -4, 3, 2, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ] ], 1 ] - ], - [ - [ [ [ -5, 3, 1, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -5, 3, 1, 2, 1, 0 ], [ -3, 1, 1, 3, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ] ], 1 ], - [ [ [ -3, 0, 1, 2, 1, 0 ], [ -3, 1, 1, 3, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ] ], 1 ] - ] - ] -], -"last_changes": -[ - [ [ -5, 3, 1, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ], [ -4, 3, 2, 2, 1, 0 ], [ -2, 2, 1, 1, 1, 0 ] ], - [ [ -5, 3, 1, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ], [ -4, 3, 2, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ] ], - [ [ -5, 3, 1, 2, 1, 0 ], [ -3, 2, 1, 2, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ] ], - [ [ -5, 3, 1, 2, 1, 0 ], [ -3, 1, 1, 3, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ] ], - [ [ -3, 0, 1, 2, 1, 0 ], [ -3, 1, 1, 3, 1, 0 ], [ -2, 1, 0, 2, 1, 0 ], [ -2, 1, 1, 2, 1, 0 ] ] -], -"cur_uid": "7ede7adb", -"ref_uid": "6522664c", -"order_seed": 455950, -"dur_seed": 308053, -"motifs_seed": 206233, -"entrances_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"passages_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"exits_probs_vals": [ 0, 0, 0, 1, 1, 0, 0.5, 0.5, 0.5, 1, 0.5 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1200 ], [ -702, 1200 ], [ -702, 1200 ] ], -"step_probs_vals": [ 0, 1200, 0.0061728395061728, 0.10227272727273, 0.074074074074074, 0.10227272727273, 0.2037037037037, 0.090909090909091, 0.45679012345679, 0.011363636363636, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.7880658436214, 0.034090909090909, 1, 0.034090909090909 ], -"passages_weights": [ 1, 0.47, 0.43, 1, 0.7 ], -"hd_exp": 7, -"hd_invert": 0, -"order": -[ - [ [ 2, 3 ], [ 0, 1 ], [ ] ], - [ [ 1, 2 ], [ 0, 3 ], [ ] ], - [ [ 2, 1 ], [ 3, 0 ], [ ] ], - [ [ 0, 1, 2 ], [ 3 ], [ ] ], - [ [ 2, 3 ], [ 1, 0 ], [ ] ], - [ [ 2, 1, 0 ], [ 3 ], [ ] ], - [ [ 1, 0, 2 ], [ 3 ], [ ] ], - [ [ 2, 0, 1 ], [ 3 ], [ ] ], - [ [ 0, 1 ], [ 2, 3 ], [ ] ], - [ [ 3 ], [ 2, 1, 0 ], [ ] ] -], -"sus_weights": [ 0.35, 0.37, 0.38 ], -"order_size": [ 10.091836734694, 10.091836734694 ], -"passages_size": [ 0, 0 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/lilypond/part_I.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/lilypond/part_I.ly deleted file mode 100644 index 41fe1e5..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/lilypond/part_I.ly +++ /dev/null @@ -1,18 +0,0 @@ -{ - { g'1^\markup { \pad-markup #0.2 "-21"} ~ } - \bar "|" - { g'2 b'2^\markup { \pad-markup #0.2 "-34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} } - \bar "|" - { g1^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} } - \bar "|" - { d'1^\markup { \pad-markup #0.2 "-19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { d'2 e'2^\markup { \pad-markup #0.2 "-36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }} } - \bar "|" - { fis'2^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} a'2^\markup { \pad-markup #0.2 "+10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }} ~ } - \bar "|" - { a'2 c''2^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } - \bar "|" - { c''1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/lilypond/part_II.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/lilypond/part_II.ly deleted file mode 100644 index ce1994b..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/lilypond/part_II.ly +++ /dev/null @@ -1,18 +0,0 @@ -{ - { b1^\markup { \pad-markup #0.2 "-34"} ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 ~ } - \bar "|" - { b1 } - \bar "|" - { fis'1^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} } - \bar "|" - { gis'1^\markup { \pad-markup #0.2 "-9"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/lilypond/part_III.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/lilypond/part_III.ly deleted file mode 100644 index e5a072c..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/lilypond/part_III.ly +++ /dev/null @@ -1,18 +0,0 @@ -{ - { fis2^\markup { \pad-markup #0.2 "-33"} c'2^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }} ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'1 ~ } - \bar "|" - { c'2 g'2^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'1 ~ } - \bar "|" - { g'2 a'2^\markup { \pad-markup #0.2 "+46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }}} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/lilypond/part_IV.ly b/resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/lilypond/part_IV.ly deleted file mode 100644 index bf1c7e0..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/7ede7adb/lilypond/part_IV.ly +++ /dev/null @@ -1,18 +0,0 @@ -{ - { gis'1^\markup { \pad-markup #0.2 "+34"} } - \bar "|" - { c''1^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { c''2 g,2^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { g,1 } - \bar "|" - { d1^\markup { \pad-markup #0.2 "-19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1 ~ } - \bar "|" - { d1} -\bar "||" -} \ No newline at end of file diff --git a/resources/resources_bak_2024_01_03/string_quartet_3_rise/tmp/tmp_mus_model.json b/resources/resources_bak_2024_01_03/string_quartet_3_rise/tmp/tmp_mus_model.json deleted file mode 100644 index 1a3fb49..0000000 --- a/resources/resources_bak_2024_01_03/string_quartet_3_rise/tmp/tmp_mus_model.json +++ /dev/null @@ -1,274 +0,0 @@ -{ -"music_data": -[ - [ - [ - [ [ [ 1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0 ], - [ [ [ 1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0.25 ], - [ [ [ 1, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0.25 ] - ], - [ - [ [ [ 1, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, -1, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 0 ], - [ [ [ 0, -1, 0, 1, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 0.25 ], - [ [ [ 0, -1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 0.25 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 0 ], - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 0, -1, 0, 1, 0, 0 ] ], 0.25 ] - ], - [ - [ [ [ 1, -1, 0, 0, -1, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 0, -1, 0, 1, 0, 0 ] ], 0.25 ], - [ [ [ 1, -2, 0, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 0, -1, 0, 1, 0, 0 ] ], 0 ], - [ [ [ 1, -2, 0, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0 ], - [ [ [ 1, -2, 0, -1, 0, 0 ], [ 2, -2, 0, -1, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0.25 ] - ], - [ - [ [ [ 1, -2, 0, -1, 0, 0 ], [ 2, -2, 0, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0 ], - [ [ [ 1, -2, 0, -1, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0.5 ], - [ [ [ 0, 0, 0, -1, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, -1, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0.25 ] - ], - [ - [ [ [ 0, 0, 0, -1, 0, 0 ], [ 1, -1, 1, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0.5 ], - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 1, -1, 1, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0 ], - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 1, -1, 1, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ] ], 0.5 ] - ], - [ - [ [ [ 2, -1, -1, -2, 0, 0 ], [ 1, -1, 1, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ] ], 0 ], - [ [ [ 2, -1, -1, -2, 0, 0 ], [ 1, -1, 1, -1, 0, 0 ], [ 3, -1, -1, -2, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ] ], 0 ], - [ [ [ 2, -1, -1, -2, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ], [ 3, -1, -1, -2, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ] ], 0.5 ], - [ [ [ 0, -1, -1, 0, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ], [ 3, -1, -1, -2, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ] ], 0.25 ] - ], - [ - [ [ [ 0, -1, -1, 0, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ], [ 3, -1, -1, -2, 0, 0 ], [ 2, -1, -1, -2, 0, 0 ] ], 0 ], - [ [ [ 0, -1, -1, 0, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ], [ 3, -1, -1, -2, 0, 0 ], [ 2, -1, -1, -2, 0, 0 ] ], 0 ], - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ], [ 3, -1, -1, -2, 0, 0 ], [ 2, -1, -1, -2, 0, 0 ] ], 0.25 ], - [ [ [ 1, -1, -1, -2, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ], [ 3, -1, -1, -2, 0, 0 ], [ 2, -1, -1, -2, 0, 0 ] ], 0 ], - [ [ [ 1, -1, -1, -2, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ], [ 3, -1, -1, -2, 0, 0 ], [ 3, -1, -1, -3, 0, 0 ] ], 0.25 ], - [ [ [ 2, -1, -1, -3, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ], [ 3, -1, -1, -2, 0, 0 ], [ 3, -1, -1, -3, 0, 0 ] ], 0.25 ], - [ [ [ 2, -1, -1, -2, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ], [ 3, -1, -1, -2, 0, 0 ], [ 3, -1, -1, -3, 0, 0 ] ], 0.25 ], - [ [ [ 2, -1, -1, -2, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ], [ 3, -1, -1, -2, 0, 0 ], [ 2, -1, 0, -2, 0, 0 ] ], 0.25 ] - ], - [ - [ [ [ 2, -1, -1, -2, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ], [ 3, -1, -1, -2, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0 ], - [ [ [ 1, -1, -1, -1, 0, 1 ], [ 2, -1, -1, -1, 0, 0 ], [ 3, -1, -1, -2, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0 ], - [ [ [ 1, -1, -1, -1, 0, 1 ], [ 2, -1, -1, -1, 0, 0 ], [ 3, -1, -1, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0.5 ], - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ], [ 3, -1, -1, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0.25 ] - ], - [ - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ], [ 3, -1, -1, -1, 0, 0 ], [ 2, -1, -2, -1, 0, 0 ] ], 0 ], - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 3, -1, -2, -1, 0, 0 ], [ 3, -1, -1, -1, 0, 0 ], [ 2, -1, -2, -1, 0, 0 ] ], 0 ], - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 3, -1, -2, -1, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ], [ 2, -1, -2, -1, 0, 0 ] ], 0.25 ], - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 2, 0, -1, -1, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ], [ 2, -1, -2, -1, 0, 0 ] ], 0.25 ] - ], - [ - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 2, -1, -1, -1, 0, 1 ], [ 2, -1, -1, -1, 0, 0 ], [ 2, -1, -2, -1, 0, 0 ] ], 0.25 ], - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 2, -1, -1, -1, 0, 1 ], [ 2, -1, -1, -1, 0, 0 ], [ 3, -2, -1, -1, 0, 0 ] ], 0 ], - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 2, -1, -1, -1, 0, 1 ], [ 2, -1, -1, -2, 0, 0 ], [ 3, -2, -1, -1, 0, 0 ] ], 0.25 ] - ], - [ - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 2, -1, -1, -1, 0, 1 ], [ 1, -1, 0, -1, 0, 0 ], [ 3, -2, -1, -1, 0, 0 ] ], 0 ], - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 2, -1, -1, -1, 0, 1 ], [ 1, -1, 0, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ] ], 0.5 ], - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ] ], 0.25 ], - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 2, 0, -1, -1, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ] ], 0.5 ], - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 2, 0, -1, -1, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 2, -2, -1, -1, 0, 0 ] ], 0.25 ], - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 2, 0, -1, -1, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ], [ 2, -2, -1, -1, 0, 0 ] ], 0 ], - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 2, 0, -1, -1, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0.25 ], - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 2, 0, -1, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0.25 ] - ], - [ - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 2, 0, -1, -1, 0, 0 ], [ 3, -1, -1, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0.5 ], - [ [ [ 0, 1, -1, -1, 0, 0 ], [ 2, 0, -1, -1, 0, 0 ], [ 3, -1, -1, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0 ], - [ [ [ 0, 1, -1, -1, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ], [ 3, -1, -1, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0 ], - [ [ [ 0, 1, -1, -1, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ], [ 2, 0, -1, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0.5 ], - [ [ [ 0, 1, -1, -1, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0.25 ], - [ [ [ 0, 1, -1, -1, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0 ], - [ [ [ 0, 0, -1, -1, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ], [ 2, -1, -1, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0.25 ], - [ [ [ 0, 0, -1, -1, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ], [ 0, 1, -1, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0.5 ] - ], - [ - [ [ [ 1, 0, -1, -2, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ], [ 0, 1, -1, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0.25 ], - [ [ [ 1, 0, -1, -2, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ], [ 2, 0, -1, -2, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0 ], - [ [ [ 1, 0, -1, -2, 0, 0 ], [ 2, 0, -2, -1, 0, 0 ], [ 2, 0, -1, -2, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0.25 ], - [ [ [ 1, 0, -1, -2, 0, 0 ], [ 2, 0, -2, -1, 0, 0 ], [ 2, 0, -1, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0.5 ], - [ [ [ 1, 0, -1, -2, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 2, 0, -1, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0.5 ], - [ [ [ 1, 0, -1, -2, 0, 0 ], [ 2, 0, -1, -2, 0, 0 ], [ 2, 0, -1, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0 ], - [ [ [ 0, 0, 0, -1, 0, 0 ], [ 2, 0, -1, -2, 0, 0 ], [ 2, 0, -1, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0.25 ] - ], - [ - [ [ [ 0, 0, 0, -1, 0, 0 ], [ 2, 0, -1, -2, 0, 0 ], [ 3, 0, -1, -2, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0 ], - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 2, 0, -1, -2, 0, 0 ], [ 3, 0, -1, -2, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0.25 ], - [ [ [ 1, -1, -1, -1, 0, 0 ], [ 2, 0, -1, -1, 0, 0 ], [ 3, 0, -1, -2, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0.25 ] - ], - [ - [ [ [ 0, 0, -1, -1, 0, 0 ], [ 2, 0, -1, -1, 0, 0 ], [ 3, 0, -1, -2, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 0 ], - [ [ [ 0, 0, -1, -1, 0, 0 ], [ 2, 0, -1, -1, 0, 0 ], [ 3, 0, -1, -2, 0, 0 ], [ 2, 0, -1, -2, 0, 0 ] ], 0 ], - [ [ [ 0, 0, -1, -1, 0, 0 ], [ 3, 0, -2, -2, 0, 0 ], [ 3, 0, -1, -2, 0, 0 ], [ 2, 0, -1, -2, 0, 0 ] ], 0.5 ], - [ [ [ 0, 0, -1, -1, 0, 0 ], [ 3, 0, -2, -2, 0, 0 ], [ 3, 0, -1, -2, 0, 0 ], [ 3, 0, -1, -3, 0, 0 ] ], 0 ], - [ [ [ 1, 0, -1, -2, 0, 0 ], [ 3, 0, -2, -2, 0, 0 ], [ 3, 0, -1, -2, 0, 0 ], [ 3, 0, -1, -3, 0, 0 ] ], 0.25 ], - [ [ [ 2, 0, -2, -2, 0, 0 ], [ 3, 0, -2, -2, 0, 0 ], [ 3, 0, -1, -2, 0, 0 ], [ 3, 0, -1, -3, 0, 0 ] ], 0 ], - [ [ [ 2, 0, -2, -2, 0, 0 ], [ 2, 1, -1, -2, 0, 0 ], [ 3, 0, -1, -2, 0, 0 ], [ 3, 0, -1, -3, 0, 0 ] ], 0.25 ] - ], - [ - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 2, 1, -1, -2, 0, 0 ], [ 3, 0, -1, -2, 0, 0 ], [ 3, 0, -1, -3, 0, 0 ] ], 0.25 ], - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 2, 1, -1, -2, 0, 0 ], [ 3, 0, -1, -2, 0, 0 ], [ 2, 1, -2, -2, 0, 0 ] ], 0.25 ], - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 2, 1, -1, -2, 0, 0 ], [ 2, 2, -1, -2, 0, 0 ], [ 2, 1, -2, -2, 0, 0 ] ], 0.5 ] - ], - [ - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 2, 1, -1, -2, 0, 0 ], [ 3, 1, -2, -2, 0, 0 ], [ 2, 1, -2, -2, 0, 0 ] ], 0 ], - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 2, 1, -1, -2, 0, 0 ], [ 3, 1, -2, -2, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 0 ], - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 3, 1, -1, -3, 0, 0 ], [ 3, 1, -2, -2, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ] ], 0.25 ], - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 3, 1, -1, -3, 0, 0 ], [ 3, 1, -2, -2, 0, 0 ], [ 2, 1, -1, -2, 0, 0 ] ], 0 ], - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 1, 2, -1, -2, 0, 0 ], [ 3, 1, -2, -2, 0, 0 ], [ 2, 1, -1, -2, 0, 0 ] ], 0.25 ] - ], - [ - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 2, 1, -2, -2, 0, 0 ], [ 3, 1, -2, -2, 0, 0 ], [ 2, 1, -1, -2, 0, 0 ] ], 0 ], - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 2, 1, -2, -2, 0, 0 ], [ 3, 1, -2, -2, 0, 0 ], [ 3, 1, -1, -3, 0, 0 ] ], 0 ], - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 2, 1, -2, -2, 0, 0 ], [ 2, 2, -1, -2, 0, 0 ], [ 3, 1, -1, -3, 0, 0 ] ], 0.5 ], - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 2, 1, -2, -2, 0, 0 ], [ 2, 1, -1, -2, 1, 0 ], [ 3, 1, -1, -3, 0, 0 ] ], 0 ], - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 1, 1, -1, -1, 0, 0 ], [ 2, 1, -1, -2, 1, 0 ], [ 3, 1, -1, -3, 0, 0 ] ], 0.375 ], - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 2, 1, -1, -2, 0, 0 ], [ 2, 1, -1, -2, 1, 0 ], [ 3, 1, -1, -3, 0, 0 ] ], 0 ], - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 2, 1, -1, -2, 0, 0 ], [ 2, 0, -1, -2, 0, 0 ], [ 3, 1, -1, -3, 0, 0 ] ], 0.25 ] - ], - [ - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 1, 1, -1, -2, -1, 0 ], [ 2, 0, -1, -2, 0, 0 ], [ 3, 1, -1, -3, 0, 0 ] ], 0.25 ], - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 1, 1, -1, -2, -1, 0 ], [ 2, 0, -1, -2, 0, 0 ], [ 2, 1, 0, -2, 0, 0 ] ], 0 ], - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 1, 1, -1, -2, -1, 0 ], [ 1, 2, -1, -2, 0, 0 ], [ 2, 1, 0, -2, 0, 0 ] ], 0.5 ], - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 1, 1, -1, -2, -1, 0 ], [ 2, 1, -1, -2, 0, 0 ], [ 2, 1, 0, -2, 0, 0 ] ], 0 ], - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 1, 1, -1, -2, -1, 0 ], [ 2, 1, -1, -2, 0, 0 ], [ 3, 0, -1, -2, 0, 0 ] ], 0.5 ], - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 1, 1, -1, -2, -1, 0 ], [ 2, 1, -1, -2, 0, 0 ], [ 3, 1, -1, -2, -1, 0 ] ], 0.25 ], - [ [ [ 1, 1, -1, -2, 0, 0 ], [ 1, 1, -1, -2, -1, 0 ], [ 2, 1, -1, -2, -1, 0 ], [ 3, 1, -1, -2, -1, 0 ] ], 0.25 ] - ], - [ - [ [ [ 1, 2, -1, -2, -1, 0 ], [ 1, 1, -1, -2, -1, 0 ], [ 2, 1, -1, -2, -1, 0 ], [ 3, 1, -1, -2, -1, 0 ] ], 0.25 ], - [ [ [ 1, 2, -1, -2, -1, 0 ], [ 1, 1, -1, -2, -1, 0 ], [ 2, 1, -1, -2, -1, 0 ], [ 2, 2, -1, -2, -1, 0 ] ], 0.25 ], - [ [ [ 1, 2, -1, -2, -1, 0 ], [ 1, 1, -1, -2, -1, 0 ], [ 3, 1, -1, -3, -1, 0 ], [ 2, 2, -1, -2, -1, 0 ] ], 0.25 ], - [ [ [ 1, 1, -1, -2, -1, 1 ], [ 1, 1, -1, -2, -1, 0 ], [ 3, 1, -1, -3, -1, 0 ], [ 2, 2, -1, -2, -1, 0 ] ], 0 ], - [ [ [ 1, 1, -1, -2, -1, 1 ], [ 1, 1, -1, -2, -1, 0 ], [ 2, 1, 0, -2, -1, 0 ], [ 2, 2, -1, -2, -1, 0 ] ], 0.5 ], - [ [ [ 1, 1, -1, -1, -1, 0 ], [ 1, 1, -1, -2, -1, 0 ], [ 2, 1, 0, -2, -1, 0 ], [ 2, 2, -1, -2, -1, 0 ] ], 0.25 ], - [ [ [ 2, 1, -1, -2, -1, 0 ], [ 1, 1, -1, -2, -1, 0 ], [ 2, 1, 0, -2, -1, 0 ], [ 2, 2, -1, -2, -1, 0 ] ], 0.5 ], - [ [ [ 2, 1, -1, -2, -1, 0 ], [ 1, 1, -1, -2, -1, 0 ], [ 2, 1, 0, -2, -1, 0 ], [ 3, 1, -1, -2, -1, 0 ] ], 0.5 ] - ], - [ - [ [ [ 2, 1, -1, -2, -1, 0 ], [ 1, 1, 0, -2, -1, 0 ], [ 2, 1, 0, -2, -1, 0 ], [ 3, 1, -1, -2, -1, 0 ] ], 0.5 ], - [ [ [ 1, 2, 0, -2, -1, 0 ], [ 1, 1, 0, -2, -1, 0 ], [ 2, 1, 0, -2, -1, 0 ], [ 3, 1, -1, -2, -1, 0 ] ], 0.5 ], - [ [ [ 1, 2, 0, -2, -1, 0 ], [ 1, 1, 0, -2, -1, 0 ], [ 2, 1, 0, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0.25 ] - ], - [ - [ [ [ 0, 1, 0, -2, -1, 0 ], [ 1, 1, 0, -2, -1, 0 ], [ 2, 1, 0, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0 ], - [ [ [ 0, 1, 0, -2, -1, 0 ], [ 1, 1, 0, -2, -1, 0 ], [ 1, 3, 0, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0.5 ], - [ [ [ 0, 1, 0, -2, -1, 0 ], [ 1, 2, 0, -2, -1, 0 ], [ 1, 3, 0, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0.25 ], - [ [ [ 0, 1, 0, -2, -1, 0 ], [ 0, 2, 0, -2, -1, 0 ], [ 1, 3, 0, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0 ], - [ [ [ -1, 3, 0, -2, -1, 0 ], [ 0, 2, 0, -2, -1, 0 ], [ 1, 3, 0, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0.625 ] - ], - [ - [ [ [ -1, 3, 0, -2, -1, 0 ], [ 0, 2, 0, -2, -1, 0 ], [ 1, 2, 0, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0.25 ], - [ [ [ -1, 2, 0, -2, -1, 0 ], [ 0, 2, 0, -2, -1, 0 ], [ 1, 2, 0, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0 ], - [ [ [ -1, 2, 0, -2, -1, 0 ], [ 0, 2, 0, -2, -1, 0 ], [ 1, 2, 0, -2, -1, 0 ], [ 1, 3, 0, -2, -1, 0 ] ], 0.5 ], - [ [ [ 0, 3, 0, -2, -1, 0 ], [ 0, 2, 0, -2, -1, 0 ], [ 1, 2, 0, -2, -1, 0 ], [ 1, 3, 0, -2, -1, 0 ] ], 0 ], - [ [ [ 0, 3, 0, -2, -1, 0 ], [ 0, 2, 0, -2, -1, 0 ], [ 1, 1, 0, -2, -1, 0 ], [ 1, 3, 0, -2, -1, 0 ] ], 0.25 ], - [ [ [ 0, 3, 0, -2, -1, 0 ], [ 0, 2, 0, -2, -1, 0 ], [ 1, 1, 0, -2, -1, 0 ], [ 1, 2, 0, -2, -1, 0 ] ], 0.5 ], - [ [ [ 0, 3, 0, -2, -1, 0 ], [ 0, 2, 0, -2, -1, 0 ], [ 1, 1, 0, -2, -1, 0 ], [ 2, 1, 0, -2, -1, 0 ] ], 0.5 ] - ], - [ - [ [ [ 0, 3, 0, -2, -1, 0 ], [ 0, 2, 0, -2, -1, 0 ], [ 1, 1, 0, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0.25 ], - [ [ [ 2, 1, 0, -2, -1, 0 ], [ 0, 2, 0, -2, -1, 0 ], [ 1, 1, 0, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0 ], - [ [ [ 2, 1, 0, -2, -1, 0 ], [ 0, 2, 0, -2, -1, 0 ], [ 1, 2, 0, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0.25 ], - [ [ [ 1, 3, 0, -2, -1, 0 ], [ 0, 2, 0, -2, -1, 0 ], [ 1, 2, 0, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0 ], - [ [ [ 1, 3, 0, -2, -1, 0 ], [ 0, 2, 0, -2, -1, 0 ], [ 1, 2, 0, -2, -1, 0 ], [ 1, 1, 0, -2, -1, 0 ] ], 0.5 ] - ], - [ - [ [ [ 1, 3, 0, -2, -1, 0 ], [ 0, 2, 0, -2, -1, 0 ], [ 1, 2, 0, -2, -1, 0 ], [ 0, 3, 0, -2, -1, 0 ] ], 0.25 ], - [ [ [ 1, 3, 0, -2, -1, 0 ], [ 1, 2, 0, -3, -1, 0 ], [ 1, 2, 0, -2, -1, 0 ], [ 0, 3, 0, -2, -1, 0 ] ], 0.25 ], - [ [ [ 2, 2, -1, -2, -1, 0 ], [ 1, 2, 0, -3, -1, 0 ], [ 1, 2, 0, -2, -1, 0 ], [ 0, 3, 0, -2, -1, 0 ] ], 0.25 ], - [ [ [ 2, 2, -1, -2, -1, 0 ], [ 1, 2, 0, -3, -1, 0 ], [ 1, 2, 0, -2, -1, 0 ], [ 1, 2, 1, -2, -1, 0 ] ], 0 ], - [ [ [ 2, 2, -1, -2, -1, 0 ], [ 0, 2, 1, -2, -1, 0 ], [ 1, 2, 0, -2, -1, 0 ], [ 1, 2, 1, -2, -1, 0 ] ], 0.25 ], - [ [ [ 2, 2, -1, -2, -1, 0 ], [ 0, 2, 1, -2, -1, 0 ], [ 1, 2, 0, -2, -1, 0 ], [ 1, 3, 0, -2, -1, 0 ] ], 0 ], - [ [ [ 2, 2, -1, -2, -1, 0 ], [ 1, 2, -1, -2, -1, 0 ], [ 1, 2, 0, -2, -1, 0 ], [ 1, 3, 0, -2, -1, 0 ] ], 0.25 ], - [ [ [ 2, 2, -1, -2, -1, 0 ], [ 1, 2, -1, -2, -1, 0 ], [ 1, 2, 0, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0.25 ] - ], - [ - [ [ [ 1, 3, 0, -2, -1, 0 ], [ 1, 2, -1, -2, -1, 0 ], [ 1, 2, 0, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0 ], - [ [ [ 1, 3, 0, -2, -1, 0 ], [ 1, 2, -1, -2, -1, 0 ], [ 2, 2, 0, -3, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0.25 ], - [ [ [ 1, 3, 0, -2, -1, 0 ], [ 0, 2, 0, -2, -1, 0 ], [ 2, 2, 0, -3, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0 ], - [ [ [ 1, 3, 0, -2, -1, 0 ], [ 0, 2, 0, -2, -1, 0 ], [ 0, 3, 0, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0.25 ], - [ [ [ 1, 3, 0, -2, -1, 0 ], [ 0, 2, 0, -2, -1, 0 ], [ 1, 2, -1, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0 ], - [ [ [ 1, 3, 0, -2, -1, 0 ], [ 0, 3, 0, -2, -1, 0 ], [ 1, 2, -1, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0 ], - [ [ [ 2, 2, -1, -2, -1, 0 ], [ 0, 3, 0, -2, -1, 0 ], [ 1, 2, -1, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0.25 ] - ], - [ - [ [ [ 1, 2, 0, -2, -1, 0 ], [ 0, 3, 0, -2, -1, 0 ], [ 1, 2, -1, -2, -1, 0 ], [ 2, 2, 0, -2, -1, 0 ] ], 0 ], - [ [ [ 1, 2, 0, -2, -1, 0 ], [ 0, 3, 0, -2, -1, 0 ], [ 1, 2, -1, -2, -1, 0 ], [ 1, 2, -1, -1, -1, 0 ] ], 0 ], - [ [ [ 1, 2, 0, -2, -1, 0 ], [ 1, 2, -1, -2, -1, -1 ], [ 1, 2, -1, -2, -1, 0 ], [ 1, 2, -1, -1, -1, 0 ] ], 0.25 ], - [ [ [ 1, 2, 0, -2, -1, 0 ], [ 1, 2, -1, -2, -1, -1 ], [ 1, 2, -1, -2, -1, 0 ], [ 2, 2, -1, -2, -1, 0 ] ], 0 ], - [ [ [ 2, 1, -1, -2, -1, 0 ], [ 1, 2, -1, -2, -1, -1 ], [ 1, 2, -1, -2, -1, 0 ], [ 2, 2, -1, -2, -1, 0 ] ], 0.5 ], - [ [ [ 2, 2, -1, -2, -1, -1 ], [ 1, 2, -1, -2, -1, -1 ], [ 1, 2, -1, -2, -1, 0 ], [ 2, 2, -1, -2, -1, 0 ] ], 0 ], - [ [ [ 2, 2, -1, -2, -1, -1 ], [ 1, 2, -1, -2, -1, -1 ], [ 1, 2, -1, -2, -1, 0 ], [ 2, 3, -1, -2, -1, 0 ] ], 0.5 ] - ], - [ - [ [ [ 2, 2, -1, -2, -1, -1 ], [ 1, 2, -1, -2, -1, -1 ], [ 1, 3, -1, -2, -1, -1 ], [ 2, 3, -1, -2, -1, 0 ] ], 0 ], - [ [ [ 2, 2, -1, -2, -1, -1 ], [ -1, 3, -1, -1, -1, 0 ], [ 1, 3, -1, -2, -1, -1 ], [ 2, 3, -1, -2, -1, 0 ] ], 0 ], - [ [ [ 0, 3, -1, -1, -1, 0 ], [ -1, 3, -1, -1, -1, 0 ], [ 1, 3, -1, -2, -1, -1 ], [ 2, 3, -1, -2, -1, 0 ] ], 0.25 ], - [ [ [ 1, 3, -1, -2, -1, 0 ], [ -1, 3, -1, -1, -1, 0 ], [ 1, 3, -1, -2, -1, -1 ], [ 2, 3, -1, -2, -1, 0 ] ], 0 ], - [ [ [ 1, 3, -1, -2, -1, 0 ], [ 0, 3, -1, -2, -1, 0 ], [ 1, 3, -1, -2, -1, -1 ], [ 2, 3, -1, -2, -1, 0 ] ], 0.25 ] - ] - ] -], -"last_changes": -[ - [ [ 2, 2, -1, -2, -1, -1 ], [ 1, 2, -1, -2, -1, -1 ], [ 1, 3, -1, -2, -1, -1 ], [ 2, 3, -1, -2, -1, 0 ] ], - [ [ 2, 2, -1, -2, -1, -1 ], [ -1, 3, -1, -1, -1, 0 ], [ 1, 3, -1, -2, -1, -1 ], [ 2, 3, -1, -2, -1, 0 ] ], - [ [ 0, 3, -1, -1, -1, 0 ], [ -1, 3, -1, -1, -1, 0 ], [ 1, 3, -1, -2, -1, -1 ], [ 2, 3, -1, -2, -1, 0 ] ], - [ [ 1, 3, -1, -2, -1, 0 ], [ -1, 3, -1, -1, -1, 0 ], [ 1, 3, -1, -2, -1, -1 ], [ 2, 3, -1, -2, -1, 0 ] ], - [ [ 1, 3, -1, -2, -1, 0 ], [ 0, 3, -1, -2, -1, 0 ], [ 1, 3, -1, -2, -1, -1 ], [ 2, 3, -1, -2, -1, 0 ] ] -], -"cur_uid": "tmp", -"ref_uid": "nil", -"order_seed": 482760, -"dur_seed": 662444, -"motifs_seed": 696864, -"entrances_probs_vals": [ 0.63, 0, 0, 0, 1, 0.019607843137255, 0, 0.2156862745098, 0, 0.2516339869281, 0.76351351351351, 0.31045751633987, 0, 0.44771241830065, 0, 0.50653594771242, 0.41216216216216, 0.5359477124183, 0, 1, 0 ], -"passages_probs_vals": [ 0.63, 0, 0, 0, 1, 0.019607843137255, 0, 0.2156862745098, 0, 0.2516339869281, 0.76351351351351, 0.31045751633987, 0, 0.44771241830065, 0, 0.50653594771242, 0.41216216216216, 0.5359477124183, 0, 1, 0 ], -"exits_probs_vals": [ 0.63, 0, 0, 0, 1, 0.019607843137255, 0, 0.2156862745098, 0, 0.2516339869281, 0.76351351351351, 0.31045751633987, 0, 0.44771241830065, 0, 0.50653594771242, 0.41216216216216, 0.5359477124183, 0, 1, 0 ], -"ranges": [ [ -2400, 1200 ], [ -1200, 1453 ], [ -702, 1694 ], [ -702, 1973 ] ], -"step_probs_vals": [ -1200, 1200, 0.0041152263374486, 0.0056818181818179, 0.080246913580247, 0.02840909090909, 0.20781893004115, 0.028409090909091, 0.41152263374486, 0, 0.44650205761317, 0.16477272727273, 0.47736625514403, 0, 0.53086419753086, 0, 0.54320987654321, 0.92045454545455, 0.58641975308642, 0.92613636363636, 0.61111111111111, 0, 0.7880658436214, 0.034090909090909, 1, 0.034090909090909 ], -"passages_weights": [ 0.58, 1, 0.43, 1, 0.82 ], -"hd_exp": 10, -"hd_invert": 0, -"order": -[ - [ [ 3 ], [ 0, 2, 1, 1 ], [ ] ], - [ [ 1 ], [ 3, 0, 2, 0, 0, 3 ], [ ] ], - [ [ 2 ], [ 1, 0, 3, 1 ], [ ] ], - [ [ 3 ], [ 2, 1, 0, 1 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 3 ], [ 0, 2, 1, 0 ], [ ] ], - [ [ 2 ], [ 3, 1, 0, 0, 3, 0, 0, 3 ], [ ] ], - [ [ 1 ], [ 3, 0, 2, 0 ], [ ] ], - [ [ 0 ], [ 3, 1, 2, 1 ], [ ] ], - [ [ 0 ], [ 1, 3, 2 ], [ ] ], - [ [ 0 ], [ 2, 3, 1, 1, 3, 2, 3, 2 ], [ ] ], - [ [ 3 ], [ 2, 0, 1, 2, 2, 2, 0, 2 ], [ ] ], - [ [ 3 ], [ 0, 2, 1, 2, 1, 1, 0 ], [ ] ], - [ [ 3 ], [ 2, 0, 1 ], [ ] ], - [ [ 2 ], [ 0, 3, 1, 3, 0, 0, 1 ], [ ] ], - [ [ 1 ], [ 0, 3, 2 ], [ ] ], - [ [ 0 ], [ 2, 3, 1, 3, 1 ], [ ] ], - [ [ 0 ], [ 1, 3, 2, 2, 1, 1, 2 ], [ ] ], - [ [ 0 ], [ 1, 3, 2, 2, 3, 3, 2 ], [ ] ], - [ [ 1 ], [ 0, 3, 2, 0, 2, 0, 0, 3 ], [ ] ], - [ [ 2 ], [ 1, 0, 3 ], [ ] ], - [ [ 3 ], [ 0, 2, 1, 1, 0 ], [ ] ], - [ [ 1 ], [ 2, 0, 3, 0, 2, 3, 3 ], [ ] ], - [ [ 1 ], [ 3, 0, 2, 0, 3 ], [ ] ], - [ [ 2 ], [ 3, 1, 0, 3, 1, 3, 1, 3 ], [ ] ], - [ [ 3 ], [ 0, 2, 1, 2, 2, 1, 0 ], [ ] ], - [ [ 2 ], [ 0, 3, 1, 3, 0, 0, 3 ], [ ] ], - [ [ 3 ], [ 2, 1, 0, 0, 1 ], [ ] ] -], -"sus_weights": [ 0.69, 0, 0 ], -"order_size": [ 28, 28.275510204082 ], -"passages_size": [ 0, 6 ], -"motif_edited": "false", -"order_edited": "false" -} \ No newline at end of file diff --git a/resources/string_quartet_2/60adbbef/lilypond/part_I.ly b/resources/string_quartet_2/60adbbef/lilypond/part_I.ly index 745ebef..91557ba 100644 --- a/resources/string_quartet_2/60adbbef/lilypond/part_I.ly +++ b/resources/string_quartet_2/60adbbef/lilypond/part_I.ly @@ -19,12 +19,6 @@ \bar "|" { a'2 r2 } \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } + { r1 \fermata^8 } \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_2/60adbbef/lilypond/part_II.ly b/resources/string_quartet_2/60adbbef/lilypond/part_II.ly index e2312d8..cfe133c 100644 --- a/resources/string_quartet_2/60adbbef/lilypond/part_II.ly +++ b/resources/string_quartet_2/60adbbef/lilypond/part_II.ly @@ -20,11 +20,5 @@ { e'2 r2 } \bar "|" { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_2/60adbbef/lilypond/part_III.ly b/resources/string_quartet_2/60adbbef/lilypond/part_III.ly index e27bd19..73127e7 100644 --- a/resources/string_quartet_2/60adbbef/lilypond/part_III.ly +++ b/resources/string_quartet_2/60adbbef/lilypond/part_III.ly @@ -20,11 +20,5 @@ { cis'2 r2 } \bar "|" { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_2/60adbbef/lilypond/part_IV.ly b/resources/string_quartet_2/60adbbef/lilypond/part_IV.ly index c144b19..3eb2077 100644 --- a/resources/string_quartet_2/60adbbef/lilypond/part_IV.ly +++ b/resources/string_quartet_2/60adbbef/lilypond/part_IV.ly @@ -20,11 +20,5 @@ { a,2 r2 } \bar "|" { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_2/74b8f8d9/lilypond/part_I.ly b/resources/string_quartet_2/74b8f8d9/lilypond/part_I.ly index 607f119..6b1515c 100644 --- a/resources/string_quartet_2/74b8f8d9/lilypond/part_I.ly +++ b/resources/string_quartet_2/74b8f8d9/lilypond/part_I.ly @@ -27,12 +27,6 @@ \bar "|" { d'8.[ r16] r2. } \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } + { r1\fermata^8 } \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_2/74b8f8d9/lilypond/part_II.ly b/resources/string_quartet_2/74b8f8d9/lilypond/part_II.ly index 16c2d82..ea84dfa 100644 --- a/resources/string_quartet_2/74b8f8d9/lilypond/part_II.ly +++ b/resources/string_quartet_2/74b8f8d9/lilypond/part_II.ly @@ -28,11 +28,5 @@ { fis'8.[ r16] r2. } \bar "|" { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_2/74b8f8d9/lilypond/part_III.ly b/resources/string_quartet_2/74b8f8d9/lilypond/part_III.ly index d5db128..f0bc9d8 100644 --- a/resources/string_quartet_2/74b8f8d9/lilypond/part_III.ly +++ b/resources/string_quartet_2/74b8f8d9/lilypond/part_III.ly @@ -28,11 +28,5 @@ { f8.[ r16] r2. } \bar "|" { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_2/74b8f8d9/lilypond/part_IV.ly b/resources/string_quartet_2/74b8f8d9/lilypond/part_IV.ly index 1aeccc8..4267347 100644 --- a/resources/string_quartet_2/74b8f8d9/lilypond/part_IV.ly +++ b/resources/string_quartet_2/74b8f8d9/lilypond/part_IV.ly @@ -28,11 +28,5 @@ { a,8.[ r16] r2. } \bar "|" { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } - \bar "|" - { r1 } \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_3_rise_coda_only.json b/resources/string_quartet_3_rise_coda_only.json index 8dee13f..e73fbfc 100644 --- a/resources/string_quartet_3_rise_coda_only.json +++ b/resources/string_quartet_3_rise_coda_only.json @@ -13,6 +13,7 @@ "5ef20586", "4dd2a130", "767e70f0", - "536cac90" + "536cac90", + "5ededd80" ] } \ No newline at end of file diff --git a/resources/string_quartet_3_rise_coda_only/4dd2a130/4dd2a130_mus_model.json b/resources/string_quartet_3_rise_coda_only/4dd2a130/4dd2a130_mus_model.json index bf4b64e..65401bc 100644 --- a/resources/string_quartet_3_rise_coda_only/4dd2a130/4dd2a130_mus_model.json +++ b/resources/string_quartet_3_rise_coda_only/4dd2a130/4dd2a130_mus_model.json @@ -3,29 +3,29 @@ [ [ [ - [ [ [ -5, 5, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -4, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -5, 5, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -4, 4, 0, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], - [ [ [ -4, 4, 0, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -4, 4, 0, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -4, 4, 0, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -4, 4, 0, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] + [ [ [ -6, 5, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -6, 5, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -5, 4, 0, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], + [ [ [ -5, 4, 0, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -5, 4, 0, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -5, 4, 0, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -5, 4, 0, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] ], [ - [ [ [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], - [ [ [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -4, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -4, 4, 0, 2, -1, 2 ], [ -6, 4, 1, 2, -1, 2 ], [ -4, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] + [ [ [ -5, 4, 0, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], + [ [ [ -5, 4, 0, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -4, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -5, 4, 0, 2, -1, 2 ], [ -6, 4, 1, 2, -1, 2 ], [ -4, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] ], [ - [ [ [ -4, 4, 0, 2, -1, 2 ], [ -6, 4, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 1, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], - [ [ [ -5, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 1, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] + [ [ [ -5, 4, 0, 2, -1, 2 ], [ -6, 4, 1, 2, -1, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -5, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 1, -1, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], + [ [ [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 1, -1, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] ], [ - [ [ [ -5, 4, 1, 2, -1, 3 ], [ -5, 4, 1, 1, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], - [ [ [ -5, 4, 1, 2, -1, 3 ], [ -5, 4, -1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -5, 4, 1, 2, -1, 3 ], [ -5, 3, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], - [ [ [ -4, 3, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] + [ [ [ -6, 4, 1, 2, -1, 3 ], [ -5, 4, 1, 1, -1, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], + [ [ [ -6, 4, 1, 2, -1, 3 ], [ -5, 4, -1, 2, -1, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -6, 4, 1, 2, -1, 3 ], [ -5, 3, 1, 2, -1, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], + [ [ [ -5, 3, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] ] ] ], diff --git a/resources/string_quartet_3_rise_coda_only/4dd2a130/lilypond/part_II.ly b/resources/string_quartet_3_rise_coda_only/4dd2a130/lilypond/part_II.ly index 702338f..d5acdbf 100644 --- a/resources/string_quartet_3_rise_coda_only/4dd2a130/lilypond/part_II.ly +++ b/resources/string_quartet_3_rise_coda_only/4dd2a130/lilypond/part_II.ly @@ -1,6 +1,6 @@ { - { f''8^\markup { \pad-markup #0.2 "-38"}[ c'8^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] cis'8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}[ ais'8^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ ais'8[ c''8^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] f''4^\markup { \pad-markup #0.2 "-38"} } + { f'8^\markup { \pad-markup #0.2 "-38"}[ c'8^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] cis'8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}[ ais'8^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ ais'8[ c''8^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] f''4^\markup { \pad-markup #0.2 "-38"} } \bar "|" - { cis'1^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}} + { cis''1^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}} \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_3_rise_coda_only/4dd2a130/lilypond/part_IV.ly b/resources/string_quartet_3_rise_coda_only/4dd2a130/lilypond/part_IV.ly index 74ec7e4..e73d174 100644 --- a/resources/string_quartet_3_rise_coda_only/4dd2a130/lilypond/part_IV.ly +++ b/resources/string_quartet_3_rise_coda_only/4dd2a130/lilypond/part_IV.ly @@ -1,6 +1,6 @@ { - { c''4^\markup { \pad-markup #0.2 "-37"} cis''2.^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }} ~ } + { c'4^\markup { \pad-markup #0.2 "-37"} cis'2.^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }} ~ } \bar "|" - { cis''8[ c''8^\markup { \pad-markup #0.2 "-37"}] cis''8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }}[ ais'8^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ ais'2} + { cis'8[ c'8^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}] cis'8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↑" }}[ ais8^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ ais2} \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_3_rise_coda_only/50c2b0ad/50c2b0ad_mus_model.json b/resources/string_quartet_3_rise_coda_only/50c2b0ad/50c2b0ad_mus_model.json index 10eff06..e91ef34 100644 --- a/resources/string_quartet_3_rise_coda_only/50c2b0ad/50c2b0ad_mus_model.json +++ b/resources/string_quartet_3_rise_coda_only/50c2b0ad/50c2b0ad_mus_model.json @@ -25,34 +25,34 @@ [ [ [ -4, 4, -1, 1, -2, 2 ], [ -4, 4, 0, 2, -2, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0 ], [ [ [ -5, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -2, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], [ [ [ -5, 4, -1, 2, -2, 2 ], [ -4, 4, 0, 2, -2, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0 ], - [ [ [ -5, 4, -1, 2, -2, 2 ], [ -4, 3, -1, 2, -2, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], - [ [ [ -5, 4, -1, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], - [ [ [ -5, 4, -1, 2, -2, 2 ], [ -4, 3, -1, 2, -2, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ] + [ [ [ -5, 4, -1, 2, -2, 2 ], [ -3, 3, -1, 2, -2, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], + [ [ [ -5, 4, -1, 2, -2, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], + [ [ [ -5, 4, -1, 2, -2, 2 ], [ -3, 3, -1, 2, -2, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ] ], [ - [ [ [ -5, 4, -1, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], - [ [ [ -5, 4, -1, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -3, 4, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0 ], - [ [ [ -4, 5, -1, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -3, 4, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], - [ [ [ -4, 5, -1, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -2, 4, -1, 1, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], - [ [ [ -4, 5, -1, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -3, 4, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0 ], - [ [ [ -4, 5, -1, 2, -2, 2 ], [ -4, 3, -1, 2, -2, 2 ], [ -3, 4, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], - [ [ [ -4, 5, -1, 2, -2, 2 ], [ -4, 3, -1, 2, -2, 2 ], [ -3, 3, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ] + [ [ [ -5, 4, -1, 2, -2, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], + [ [ [ -5, 4, -1, 2, -2, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -3, 4, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0 ], + [ [ [ -5, 5, -1, 2, -2, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -3, 4, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], + [ [ [ -5, 5, -1, 2, -2, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -2, 4, -1, 1, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], + [ [ [ -5, 5, -1, 2, -2, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -3, 4, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0 ], + [ [ [ -5, 5, -1, 2, -2, 2 ], [ -3, 3, -1, 2, -2, 2 ], [ -3, 4, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], + [ [ [ -5, 5, -1, 2, -2, 2 ], [ -3, 3, -1, 2, -2, 2 ], [ -3, 3, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ] ], [ - [ [ [ -4, 5, -1, 2, -2, 2 ], [ -5, 4, 0, 2, -2, 2 ], [ -3, 3, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0 ], - [ [ [ -4, 5, -1, 2, -2, 2 ], [ -5, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], - [ [ [ -4, 5, -1, 2, -2, 2 ], [ -5, 4, -1, 2, -2, 2 ], [ -4, 4, 0, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ] + [ [ [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, 0, 2, -2, 2 ], [ -3, 3, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0 ], + [ [ [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], + [ [ [ -5, 5, -1, 2, -2, 2 ], [ -3, 4, -1, 2, -2, 2 ], [ -4, 4, 0, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ] ], [ - [ [ [ -4, 5, -1, 2, -2, 2 ], [ -5, 4, -1, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0 ], - [ [ [ -4, 5, -1, 2, -2, 2 ], [ -3, 4, -1, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0 ], - [ [ [ -3, 3, -1, 2, -2, 2 ], [ -3, 4, -1, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ] + [ [ [ -5, 5, -1, 2, -2, 2 ], [ -3, 4, -1, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0 ], + [ [ [ -5, 5, -1, 2, -2, 2 ], [ -3, 4, -1, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0 ], + [ [ [ -4, 3, -1, 2, -2, 2 ], [ -3, 4, -1, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ] ], [ - [ [ [ -4, 4, 0, 2, -2, 2 ], [ -3, 4, -1, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0 ], - [ [ [ -4, 4, 0, 2, -2, 2 ], [ -4, 5, 0, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], - [ [ [ -4, 4, 0, 2, -2, 2 ], [ -4, 4, -1, 3, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0 ], - [ [ [ -4, 4, -1, 2, -1, 2 ], [ -4, 4, -1, 3, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ] + [ [ [ -5, 4, 0, 2, -2, 2 ], [ -3, 4, -1, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0 ], + [ [ [ -5, 4, 0, 2, -2, 2 ], [ -4, 5, 0, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], + [ [ [ -5, 4, 0, 2, -2, 2 ], [ -4, 4, -1, 3, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0 ], + [ [ [ -5, 4, -1, 2, -1, 2 ], [ -4, 4, -1, 3, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ] ] ] ], diff --git a/resources/string_quartet_3_rise_coda_only/50c2b0ad/lilypond/part_III.ly b/resources/string_quartet_3_rise_coda_only/50c2b0ad/lilypond/part_III.ly index 2c18edf..33029d2 100644 --- a/resources/string_quartet_3_rise_coda_only/50c2b0ad/lilypond/part_III.ly +++ b/resources/string_quartet_3_rise_coda_only/50c2b0ad/lilypond/part_III.ly @@ -1,8 +1,8 @@ { { d'8^\markup { \pad-markup #0.2 "-18"}[ dis'8^\markup { \pad-markup #0.2 "+38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] e'8^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }}[ fis'8^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }}] ~ fis'2 ~ } \bar "|" - { fis'8[ g'8^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }}] gis8^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}[ ais8^\markup { \pad-markup #0.2 "+40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] gis8^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}[ ais8^\markup { \pad-markup #0.2 "+40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ ais4 } + { fis'8[ g'8^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }}] gis'8^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}[ ais'8^\markup { \pad-markup #0.2 "+40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] gis'8^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}[ ais'8^\markup { \pad-markup #0.2 "+40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ ais'4 } \bar "|" - { gis4^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }} g8^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }}[ dis8^\markup { \pad-markup #0.2 "+38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] dis''8^\markup { \pad-markup #0.2 "+38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}[ d''8^\markup { \pad-markup #0.2 "+26"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] cis''4^\markup { \pad-markup #0.2 "+6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }}} + { gis'4^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↓" }} g'8^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }}[ dis''8^\markup { \pad-markup #0.2 "+38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ dis''8[ d''8^\markup { \pad-markup #0.2 "+26"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] cis''4^\markup { \pad-markup #0.2 "+6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↑" }}} \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_3_rise_coda_only/50c2b0ad/lilypond/part_IV.ly b/resources/string_quartet_3_rise_coda_only/50c2b0ad/lilypond/part_IV.ly index 5f683d4..99f1bb0 100644 --- a/resources/string_quartet_3_rise_coda_only/50c2b0ad/lilypond/part_IV.ly +++ b/resources/string_quartet_3_rise_coda_only/50c2b0ad/lilypond/part_IV.ly @@ -1,8 +1,8 @@ { { ais2^\markup { \pad-markup #0.2 "+40"} fis2^\markup { \pad-markup #0.2 "-31"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } \bar "|" - { fis8[ g8^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] dis2^\markup { \pad-markup #0.2 "+38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ais'4^\markup { \pad-markup #0.2 "+40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } + { fis8[ g8^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] dis2^\markup { \pad-markup #0.2 "+38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ais4^\markup { \pad-markup #0.2 "+40"} ~ } \bar "|" - { ais'2 gis'8^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }}[ g'8^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}] a'4^\markup { \pad-markup #0.2 "-11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }}} + { ais2 gis8^\markup { \pad-markup #0.2 "+36"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }}[ g8^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}] a4^\markup { \pad-markup #0.2 "-11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }}} \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_3_rise_coda_only/536cac90/536cac90_mus_model.json b/resources/string_quartet_3_rise_coda_only/536cac90/536cac90_mus_model.json index 1017c6b..4c3d339 100644 --- a/resources/string_quartet_3_rise_coda_only/536cac90/536cac90_mus_model.json +++ b/resources/string_quartet_3_rise_coda_only/536cac90/536cac90_mus_model.json @@ -9,12 +9,12 @@ [ [ [ -6, 4, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] ], [ - [ [ [ -6, 4, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ], [ -6, 3, 1, 3, -1, 2 ] ], 0.25 ], - [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ], [ -6, 3, 1, 3, -1, 2 ] ], 0 ], - [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -6, 3, 1, 3, -1, 2 ] ], 0.25 ], - [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -5, 3, 1, 2, 0, 2 ], [ -6, 3, 1, 3, -1, 2 ] ], 0.25 ], - [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -4, 2, 1, 2, -1, 2 ], [ -6, 3, 1, 3, -1, 2 ] ], 0.25 ], - [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -5, 3, 2, 2, -1, 2 ], [ -6, 3, 1, 3, -1, 2 ] ], 0.25 ] + [ [ [ -6, 4, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ], [ -5, 3, 1, 3, -1, 2 ] ], 0.25 ], + [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ], [ -5, 3, 1, 3, -1, 2 ] ], 0 ], + [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -5, 3, 1, 3, -1, 2 ] ], 0.25 ], + [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -5, 3, 1, 2, 0, 2 ], [ -5, 3, 1, 3, -1, 2 ] ], 0.25 ], + [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -4, 2, 1, 2, -1, 2 ], [ -5, 3, 1, 3, -1, 2 ] ], 0.25 ], + [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -5, 3, 2, 2, -1, 2 ], [ -5, 3, 1, 3, -1, 2 ] ], 0.25 ] ], [ [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -5, 3, 2, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0.25 ], @@ -44,17 +44,10 @@ [ [ [ -5, 2, 1, 2, -1, 2 ], [ -4, 2, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0.25 ] ], [ - [ [ [ -5, 2, 1, 2, -1, 2 ], [ -4, 2, 1, 2, -1, 2 ], [ -3, 2, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -5, 2, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -3, 2, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -6, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -3, 2, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0.25 ] + [ [ [ -5, 2, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0.25 ] ], [ - [ [ [ -6, 3, 1, 2, 0, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -3, 2, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0 ], - [ [ [ -6, 3, 1, 2, 0, 2 ], [ -5, 3, 1, 2, 0, 2 ], [ -3, 2, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -6, 3, 1, 2, 0, 2 ], [ -4, 3, 1, 2, -2, 2 ], [ -3, 2, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0 ], - [ [ [ -5, 3, 1, 2, -2, 2 ], [ -4, 3, 1, 2, -2, 2 ], [ -3, 2, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0.5 ], - [ [ [ -6, 3, 1, 2, -2, 2 ], [ -4, 4, 1, 2, -2, 2 ], [ -3, 3, 2, 2, -2, 2 ], [ -4, 3, 1, 3, -2, 2 ] ], 1.5 ], - [ [ [ -5, 2, 1, 2, -2, 2 ], [ -4, 3, 1, 2, -2, 2 ], [ -3, 3, 1, 2, -2, 2 ], [ -3, 2, 1, 2, -2, 2 ] ], 2.25 ] + [ [ [ -5, 2, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ]], 0.25 ] ] ] ], diff --git a/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_I.ly b/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_I.ly index 4aeeb9f..814b1ff 100644 --- a/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_I.ly +++ b/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_I.ly @@ -1,14 +1,10 @@ { - { f'2^\markup { \pad-markup #0.2 "-38"} g2^\markup { \pad-markup #0.2 "+28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }} ~ } + { f'2^\markup { \pad-markup #0.2 "-38"} g'2^\markup { \pad-markup #0.2 "+28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↑" }} ~ } \bar "|" - { g8[ ais'8^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ ais'2. ~ } + { g'8[ ais'8^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ ais'2. ~ } \bar "|" { ais'1 ~ } \bar "|" - { ais'2 d''2^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }} ~ } - \bar "|" - { d''4 a'2.^\markup { \pad-markup #0.2 "+6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } - \bar "|" - { a'1} + { ais'1} \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_II.ly b/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_II.ly index 3e38076..cc4b378 100644 --- a/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_II.ly +++ b/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_II.ly @@ -3,12 +3,8 @@ \bar "|" { cis'4^\markup { \pad-markup #0.2 "+46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} c'8^\markup { \pad-markup #0.2 "-9"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}[ fis'8^\markup { \pad-markup #0.2 "-27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}] ~ fis'2 } \bar "|" - { f'8^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }}[ dis'8^\markup { \pad-markup #0.2 "-42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] cis'8^\markup { \pad-markup #0.2 "+46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}[ dis'8^\markup { \pad-markup #0.2 "+11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }}] f'4^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }} dis''4^\markup { \pad-markup #0.2 "-42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } + { f'8^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }}[ dis'8^\markup { \pad-markup #0.2 "-42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] cis'8^\markup { \pad-markup #0.2 "+46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}[ dis'8^\markup { \pad-markup #0.2 "+11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }}] f'2^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }} ~ } \bar "|" - { dis''2 gis''2^\markup { \pad-markup #0.2 "-5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ~ } - \bar "|" - { gis''4 e''2.^\markup { \pad-markup #0.2 "+8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } - \bar "|" - { e''1} + { f'1} \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_III.ly b/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_III.ly index 8b4f748..c40e7cc 100644 --- a/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_III.ly +++ b/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_III.ly @@ -3,12 +3,8 @@ \bar "|" { ais4 ~ ais8[ c'8^\markup { \pad-markup #0.2 "-9"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}] cis'8^\markup { \pad-markup #0.2 "+46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }}[ dis'8^\markup { \pad-markup #0.2 "-42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }}] cis'8^\markup { \pad-markup #0.2 "+19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}[ ais8^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ } \bar "|" - { ais4 c'4^\markup { \pad-markup #0.2 "-9"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↓" }} cis'8^\markup { \pad-markup #0.2 "+46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }}[ dis'8^\markup { \pad-markup #0.2 "-42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ dis'8[ f'8^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}] ~ } + { ais4 c'4^\markup { \pad-markup #0.2 "-9"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↓" }} cis'8^\markup { \pad-markup #0.2 "+46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }}[ dis'8^\markup { \pad-markup #0.2 "-42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] f'4^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } \bar "|" - { f'8[ dis'8^\markup { \pad-markup #0.2 "+11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] e'4^\markup { \pad-markup #0.2 "+8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }} b'2^\markup { \pad-markup #0.2 "+10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} ~ } - \bar "|" - { b'4 e'2.^\markup { \pad-markup #0.2 "+8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } - \bar "|" - { e'1} + { f'1} \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_IV.ly b/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_IV.ly index d79bdff..f87a18d 100644 --- a/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_IV.ly +++ b/resources/string_quartet_3_rise_coda_only/536cac90/lilypond/part_IV.ly @@ -3,12 +3,8 @@ \bar "|" { ais,4 ~ ais,8[ c8^\markup { \pad-markup #0.2 "-9"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] cis2^\markup { \pad-markup #0.2 "+19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 13↓" }} } \bar "|" - { dis1^\markup { \pad-markup #0.2 "-42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} } + { dis1^\markup { \pad-markup #0.2 "-42"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } \bar "|" - { f8^\markup { \pad-markup #0.2 "-38"}[ dis8^\markup { \pad-markup #0.2 "+11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }}] e4^\markup { \pad-markup #0.2 "+8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} e,2^\markup { \pad-markup #0.2 "+8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } - \bar "|" - { e,4 a,2.^\markup { \pad-markup #0.2 "+6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } - \bar "|" - { a,1} + { dis1} \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_3_rise_coda_only/5ededd80/5ededd80_mus_model.json b/resources/string_quartet_3_rise_coda_only/5ededd80/5ededd80_mus_model.json index f52e7df..9fc6a16 100644 --- a/resources/string_quartet_3_rise_coda_only/5ededd80/5ededd80_mus_model.json +++ b/resources/string_quartet_3_rise_coda_only/5ededd80/5ededd80_mus_model.json @@ -3,8 +3,20 @@ [ [ [ - [ [ [ -6, 3, 1, 2, -2, 2 ], [ -4, 4, 1, 2, -2, 2 ], [ -3, 3, 2, 2, -2, 2 ], [ -3, 3, 1, 3, -2, 2 ] ], 0.5 ], - [ [ [ -5, 2, 1, 2, -2, 2 ], [ -4, 3, 1, 2, -2, 2 ], [ -3, 3, 1, 2, -2, 2 ], [ -2, 2, 1, 2, -2, 2 ] ], 2.25 ] + [ [ [ -5, 2, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -5, 3, 1, 3, -1, 2 ], [ -4, 3, 2, 2, -1, 2 ] ], 0.25 ], + [ [ [ -5, 2, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 3 ], [ -4, 3, 1, 2, 0, 2 ] ], 0.25 ], + + [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -4, 4, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -5, 3, 1, 2, 0, 2 ], [ -4, 3, 1, 2, -1, 3 ] ], 0.25 ], + [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -5, 3, 2, 2, -1, 2 ], [ -4, 3, 1, 3, -1, 2 ] ], 0.25 ], + [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -3, 3, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -3, 3, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -6, 3, 1, 2, -1, 2 ], [ "Rest" ], [ -5, 3, 1, 2, -1, 2 ], [ -3, 3, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -6, 3, 1, 2, -1, 2 ], [ "Rest" ], [ -5, 3, 1, 2, -1, 2 ], [ -3, 3, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ "Rest" ], [ "Rest" ], [ -5, 3, 1, 2, -1, 2 ], [ -3, 3, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ "Rest" ], [ "Rest" ], [ -5, 3, 1, 2, -1, 2 ], [ -3, 3, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.5 ], + [ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 2.25 ] ] ] ], diff --git a/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_I.ly b/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_I.ly index 136105a..9d22a0a 100644 --- a/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_I.ly +++ b/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_I.ly @@ -1,6 +1,10 @@ { - { d'''4^\markup { \pad-markup #0.2 "-23"} a''2.^\markup { \pad-markup #0.2 "+6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } + { cis''8^\markup { \pad-markup #0.2 "+46"}[ dis''8^\markup { \pad-markup #0.2 "+11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 6↑" }}] f''8^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}[ fis''8^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }}] g''8^\markup { \pad-markup #0.2 "+28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}[ ais''8^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ~ ais''4 ~ } \bar "|" - { a''1} + { ais''4 ~ ais''8[ r8] r2 } + \bar "|" + { r1 } + \bar "|" + { r1 } \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_II.ly b/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_II.ly index 36fb6c9..34b1835 100644 --- a/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_II.ly +++ b/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_II.ly @@ -1,6 +1,10 @@ { - { gis''4^\markup { \pad-markup #0.2 "-5"} e''2.^\markup { \pad-markup #0.2 "+8"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } + { g'8^\markup { \pad-markup #0.2 "+28"}[ fis'8^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 6↑" }}] f'8^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}[ dis'8^\markup { \pad-markup #0.2 "+11"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↑" }}] cis'8^\markup { \pad-markup #0.2 "+46"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }}[ c'8^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }}] ais4^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } \bar "|" - { e''1} + { ais4 ~ ais8[ r8] r2 } + \bar "|" + { r1 } + \bar "|" + { r1 } \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_III.ly b/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_III.ly index bb36c57..7fa68b8 100644 --- a/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_III.ly +++ b/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_III.ly @@ -1,6 +1,10 @@ { - { b'4^\markup { \pad-markup #0.2 "+10"} e'2.^\markup { \pad-markup #0.2 "+8"} ~ } + { f'2.^\markup { \pad-markup #0.2 "-38"} ~ f'8[ r8] } \bar "|" - { e'1} + { r1 } + \bar "|" + { r1 } + \bar "|" + { r1 } \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_IV.ly b/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_IV.ly index ebe7849..fadaa75 100644 --- a/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_IV.ly +++ b/resources/string_quartet_3_rise_coda_only/5ededd80/lilypond/part_IV.ly @@ -1,6 +1,10 @@ { - { e,4^\markup { \pad-markup #0.2 "+8"} a,2.^\markup { \pad-markup #0.2 "+6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} ~ } + { dis4^\markup { \pad-markup #0.2 "-42"} ais,2.^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } \bar "|" - { a,1} + { ais,8[ r8] r2. } + \bar "|" + { r1 } + \bar "|" + { r1 } \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_3_rise_coda_only/5ef20586/5ef20586_mus_model.json b/resources/string_quartet_3_rise_coda_only/5ef20586/5ef20586_mus_model.json index c78bd2a..2e25b90 100644 --- a/resources/string_quartet_3_rise_coda_only/5ef20586/5ef20586_mus_model.json +++ b/resources/string_quartet_3_rise_coda_only/5ef20586/5ef20586_mus_model.json @@ -9,12 +9,12 @@ [ [ [ -5, 4, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -4, 4, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0.25 ], [ [ [ -5, 4, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -3, 4, 1, 1, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0 ], [ [ [ -5, 4, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ], [ -3, 4, 1, 1, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -5, 4, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0.25 ] + [ [ [ -5, 4, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0.25 ] ], [ - [ [ [ -5, 4, 1, 2, -1, 2 ], [ -5, 3, 2, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0 ], - [ [ [ -5, 4, 1, 2, -1, 2 ], [ -5, 3, 2, 2, -1, 2 ], [ -6, 4, 2, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -5, 4, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -6, 4, 2, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0.25 ] + [ [ [ -5, 4, 1, 2, -1, 2 ], [ -5, 3, 2, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0 ], + [ [ [ -5, 4, 1, 2, -1, 2 ], [ -5, 3, 2, 2, -1, 2 ], [ -5, 4, 2, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -5, 4, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -5, 4, 2, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0.25 ] ], [ [ [ [ -5, 4, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -4, 4, 1, 2, -1, 2 ], [ -4, 3, 1, 2, -1, 2 ] ], 0.25 ], diff --git a/resources/string_quartet_3_rise_coda_only/5ef20586/lilypond/part_II.ly b/resources/string_quartet_3_rise_coda_only/5ef20586/lilypond/part_II.ly index 953bcf0..2663740 100644 --- a/resources/string_quartet_3_rise_coda_only/5ef20586/lilypond/part_II.ly +++ b/resources/string_quartet_3_rise_coda_only/5ef20586/lilypond/part_II.ly @@ -1,5 +1,5 @@ { - { d''8^\markup { \pad-markup #0.2 "+30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}[ f''8^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] g''8^\markup { \pad-markup #0.2 "-7"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}[ ais8^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] gis4^\markup { \pad-markup #0.2 "+48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} f''4^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } + { d''8^\markup { \pad-markup #0.2 "+30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}[ f''8^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] g''8^\markup { \pad-markup #0.2 "-7"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↓" }}[ ais'8^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] gis'4^\markup { \pad-markup #0.2 "+48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} f''4^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ } \bar "|" { f''1} \bar "||" diff --git a/resources/string_quartet_3_rise_coda_only/5f0075ab/5f0075ab_mus_model.json b/resources/string_quartet_3_rise_coda_only/5f0075ab/5f0075ab_mus_model.json index 11843ff..59ba63a 100644 --- a/resources/string_quartet_3_rise_coda_only/5f0075ab/5f0075ab_mus_model.json +++ b/resources/string_quartet_3_rise_coda_only/5f0075ab/5f0075ab_mus_model.json @@ -19,7 +19,7 @@ [ [ [ [ -6, 4, 1, 1, -1, 2 ], [ -5, 4, 2, 1, -1, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], [ [ [ -6, 4, 1, 1, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], - [ [ [ -7, 4, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] + [ [ [ -6, 4, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] ], [ [ [ [ -5, 3, 0, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], diff --git a/resources/string_quartet_3_rise_coda_only/5f0075ab/lilypond/part_IV.ly b/resources/string_quartet_3_rise_coda_only/5f0075ab/lilypond/part_IV.ly index a3fcbc8..b67d51d 100644 --- a/resources/string_quartet_3_rise_coda_only/5f0075ab/lilypond/part_IV.ly +++ b/resources/string_quartet_3_rise_coda_only/5f0075ab/lilypond/part_IV.ly @@ -1,5 +1,5 @@ { - { f,4^\markup { \pad-markup #0.2 "-38"} g,2^\markup { \pad-markup #0.2 "-7"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ g,8[ f,8^\markup { \pad-markup #0.2 "-38"}] } + { f,4^\markup { \pad-markup #0.2 "-38"} g,2^\markup { \pad-markup #0.2 "-7"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ g,8[ f8^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] } \bar "|" { fis8^\markup { \pad-markup #0.2 "-27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }}[ f8^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ f2.} \bar "||" diff --git a/resources/string_quartet_3_rise_coda_only/61207e49/61207e49_mus_model.json b/resources/string_quartet_3_rise_coda_only/61207e49/61207e49_mus_model.json index cdac35c..f28e746 100644 --- a/resources/string_quartet_3_rise_coda_only/61207e49/61207e49_mus_model.json +++ b/resources/string_quartet_3_rise_coda_only/61207e49/61207e49_mus_model.json @@ -3,17 +3,17 @@ [ [ [ - [ [ [ -6, 6, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -6, 6, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ], [ -4, 6, -2, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -6, 6, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ], [ -5, 6, -1, 2, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -6, 6, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ] ], 0.25 ] + [ [ [ -6, 6, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -6, 6, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ], [ -4, 6, -2, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -6, 6, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ], [ -5, 6, -1, 2, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -6, 6, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ] ], 0.25 ] ], [ - [ [ [ -6, 6, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -5, 6, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -5, 6, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -5, 6, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 6, -2, 1, -2, 2 ] ], 0.25 ], - [ [ [ -5, 6, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -5, 6, -1, 2, -2, 2 ] ], 0.25 ], + [ [ [ -6, 6, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ] ], 0 ], + [ [ [ -5, 6, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ] ], 0 ], + [ [ [ -5, 6, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 7, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -5, 6, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -3, 6, -2, 1, -2, 2 ] ], 0.25 ], + [ [ [ -5, 6, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 2, -2, 2 ] ], 0.25 ], [ [ [ -5, 6, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 7, -1, 1, -2, 2 ] ], 0.25 ] ], [ @@ -31,9 +31,9 @@ ], [ [ [ [ -5, 7, -2, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 7, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -5, 7, -2, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -3, 7, -1, 0, -2, 2 ] ], 0 ], - [ [ [ -6, 8, -1, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -3, 7, -1, 0, -2, 2 ] ], 0.25 ], - [ [ [ -6, 8, -1, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 7, 0, 1, -2, 2 ] ], 0.25 ], + [ [ [ -5, 7, -2, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 7, -1, 0, -2, 2 ] ], 0 ], + [ [ [ -6, 8, -1, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 7, -1, 0, -2, 2 ] ], 0.25 ], + [ [ [ -6, 8, -1, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -5, 7, 0, 1, -2, 2 ] ], 0.25 ], [ [ [ -6, 8, -1, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -5, 8, -1, 1, -2, 2 ] ], 0 ], [ [ [ -6, 8, -1, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -5, 7, 0, 1, -2, 2 ], [ -5, 8, -1, 1, -2, 2 ] ], 0.25 ], [ [ [ -6, 8, -1, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -5, 7, 0, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 3 ] ], 0.25 ] @@ -71,27 +71,27 @@ [ [ [ -5, 6, -1, 1, -2, 2 ], [ -4, 6, -2, 1, -3, 2 ], [ -4, 6, 0, 1, -2, 2 ], [ -3, 6, -1, 1, -3, 2 ] ], 0.25 ], [ [ [ -5, 6, -1, 1, -2, 2 ], [ -5, 7, -1, 1, -3, 2 ], [ -4, 6, 0, 1, -2, 2 ], [ -3, 6, -1, 1, -3, 2 ] ], 0.25 ], [ [ [ -5, 6, -1, 1, -2, 2 ], [ -5, 7, -1, 1, -3, 2 ], [ -4, 7, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -3, 2 ] ], 0.25 ], - [ [ [ -5, 6, -1, 1, -2, 2 ], [ -5, 7, -1, 1, -3, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -3, 2 ] ], 0.25 ] + [ [ [ -5, 6, -1, 1, -2, 2 ], [ -5, 7, -1, 1, -3, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -3, 2 ] ], 0.25 ] ], [ - [ [ [ -4, 5, -1, 1, -3, 2 ], [ -5, 7, -1, 1, -3, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -3, 2 ] ], 0 ], - [ [ [ -4, 5, -1, 1, -3, 2 ], [ -5, 7, -1, 1, -3, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -3, 2 ] ], 0 ], - [ [ [ -4, 5, -1, 1, -3, 2 ], [ -5, 6, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -3, 2 ] ], 0.25 ], - [ [ [ -4, 5, -1, 1, -3, 2 ], [ -5, 6, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 4, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -4, 4, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 4, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -4, 4, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 4, -1, 1, -2, 2 ] ], 0.25 ] + [ [ [ -4, 5, -1, 1, -3, 2 ], [ -5, 7, -1, 1, -3, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -3, 2 ] ], 0 ], + [ [ [ -4, 5, -1, 1, -3, 2 ], [ -5, 7, -1, 1, -3, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -3, 2 ] ], 0 ], + [ [ [ -4, 5, -1, 1, -3, 2 ], [ -5, 6, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -3, 2 ] ], 0.25 ], + [ [ [ -4, 5, -1, 1, -3, 2 ], [ -5, 6, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -3, 4, -1, 1, -2, 2 ] ], 0 ], + [ [ [ -4, 4, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -3, 4, -1, 1, -2, 2 ] ], 0 ], + [ [ [ -4, 4, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -3, 4, -1, 1, -2, 2 ] ], 0.25 ] ], [ - [ [ [ -5, 5, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 4, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -5, 5, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -4, 5, -1, 0, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -5, 5, 0, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -5, 6, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -4, 5, -2, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ] + [ [ [ -5, 5, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -3, 4, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -5, 5, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0 ], + [ [ [ -4, 5, -1, 0, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -5, 5, 0, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -5, 6, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -4, 5, -2, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ] ], [ - [ [ [ -4, 5, -2, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 5, -2, 1, -2, 2 ] ], 0.25 ], - [ [ [ -5, 5, -1, 2, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 5, -2, 1, -2, 2 ] ], 0.25 ] + [ [ [ -4, 5, -2, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -3, 5, -2, 1, -2, 2 ] ], 0.25 ], + [ [ [ -5, 5, -1, 2, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -3, 5, -2, 1, -2, 2 ] ], 0.25 ] ] ] ], diff --git a/resources/string_quartet_3_rise_coda_only/61207e49/lilypond/part_I.ly b/resources/string_quartet_3_rise_coda_only/61207e49/lilypond/part_I.ly index c6af1e7..871d25d 100644 --- a/resources/string_quartet_3_rise_coda_only/61207e49/lilypond/part_I.ly +++ b/resources/string_quartet_3_rise_coda_only/61207e49/lilypond/part_I.ly @@ -1,7 +1,7 @@ { - { cis'2^\markup { \pad-markup #0.2 "-29"} dis'8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}[ e'8^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}] f'8^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}[ dis''8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] } + { cis''2^\markup { \pad-markup #0.2 "-29"} dis''8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}[ e''8^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}] f''8^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 7↑" }}[ dis''8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] } \bar "|" - { e''8^\markup { \pad-markup #0.2 "+13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }}[ dis''8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ dis''2 f''8^\markup { \pad-markup #0.2 "+6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }}[ g''8^\markup { \pad-markup #0.2 "-39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}] } + { e''8^\markup { \pad-markup #0.2 "+13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }}[ dis''8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ dis''2 f'8^\markup { \pad-markup #0.2 "+6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }}[ g'8^\markup { \pad-markup #0.2 "-39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}] } \bar "|" { ais'8^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}[ b'8^\markup { \pad-markup #0.2 "+15"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↑" }}] ais'4^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} b'4^\markup { \pad-markup #0.2 "-12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }} ~ b'8[ cis''8^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] } \bar "|" diff --git a/resources/string_quartet_3_rise_coda_only/61207e49/lilypond/part_II.ly b/resources/string_quartet_3_rise_coda_only/61207e49/lilypond/part_II.ly index d08b37b..e4af8bd 100644 --- a/resources/string_quartet_3_rise_coda_only/61207e49/lilypond/part_II.ly +++ b/resources/string_quartet_3_rise_coda_only/61207e49/lilypond/part_II.ly @@ -5,10 +5,10 @@ \bar "|" { g'4^\markup { \pad-markup #0.2 "-39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }} fis'8^\markup { \pad-markup #0.2 "+17"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↑" }}[ f'8^\markup { \pad-markup #0.2 "-21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}] fis'8^\markup { \pad-markup #0.2 "+34"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 13↓" }}[ gis'8^\markup { \pad-markup #0.2 "+26"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] ais'8^\markup { \pad-markup #0.2 "-23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }}[ b'8^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] ~ } \bar "|" - { b'4 cis''4^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} c''4^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} dis''8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}[ cis'8^\markup { \pad-markup #0.2 "-29"}] ~ } + { b'4 cis''4^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }} c''4^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} dis''8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }}[ cis''8^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}] ~ } \bar "|" - { cis'1 ~ } + { cis''1 ~ } \bar "|" - { cis'1} + { cis''1} \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_3_rise_coda_only/61207e49/lilypond/part_III.ly b/resources/string_quartet_3_rise_coda_only/61207e49/lilypond/part_III.ly index ce3d023..7232caa 100644 --- a/resources/string_quartet_3_rise_coda_only/61207e49/lilypond/part_III.ly +++ b/resources/string_quartet_3_rise_coda_only/61207e49/lilypond/part_III.ly @@ -7,8 +7,8 @@ \bar "|" { c'2^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↑" }} ais8^\markup { \pad-markup #0.2 "+35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }}[ a8^\markup { \pad-markup #0.2 "+23"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}] ~ a4 } \bar "|" - { gis8^\markup { \pad-markup #0.2 "-27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }}[ cis''8^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ cis''2. ~ } + { gis8^\markup { \pad-markup #0.2 "-27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 3↑" }}[ cis'8^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}] ~ cis'2. ~ } \bar "|" - { cis''1} + { cis'1} \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_3_rise_coda_only/624f7439/624f7439_mus_model.json b/resources/string_quartet_3_rise_coda_only/624f7439/624f7439_mus_model.json index 835be59..7e36c60 100644 --- a/resources/string_quartet_3_rise_coda_only/624f7439/624f7439_mus_model.json +++ b/resources/string_quartet_3_rise_coda_only/624f7439/624f7439_mus_model.json @@ -10,55 +10,55 @@ ], [ [ [ [ -6, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -3, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -3, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -3, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 0, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -3, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -3, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ] ], 0.25 ] + [ [ [ -5, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ] ], 0 ], + [ [ [ -5, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -5, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 0, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -5, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -5, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 6, -1, 1, -2, 2 ] ], 0.25 ] ], [ - [ [ [ -3, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -3, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0.25 ] + [ [ [ -5, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0 ], + [ [ [ -5, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ] ], [ - [ [ [ -3, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 6, -2, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -3, 5, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -4, 6, -2, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -4, 6, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -4, 6, -2, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -5, 6, -1, 0, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -4, 6, -2, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -5, 6, -1, 0, -2, 2 ], [ -4, 6, -1, 1, -3, 2 ], [ -4, 6, -2, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -5, 6, -1, 0, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -4, 6, -2, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -5, 6, -1, 0, -2, 2 ], [ -5, 6, -1, 1, -1, 2 ], [ -4, 6, -2, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0.25 ] + [ [ [ -5, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 6, -2, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0 ], + [ [ [ -5, 5, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -4, 6, -2, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0 ], + [ [ [ -6, 6, -1, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -4, 6, -2, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -5, 6, -1, 0, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -4, 6, -2, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0 ], + [ [ [ -5, 6, -1, 0, -2, 2 ], [ -4, 6, -1, 1, -3, 2 ], [ -4, 6, -2, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -5, 6, -1, 0, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -4, 6, -2, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -5, 6, -1, 0, -2, 2 ], [ -5, 6, -1, 1, -1, 2 ], [ -4, 6, -2, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ] ], [ - [ [ [ -5, 6, -1, 0, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -4, 6, -2, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -5, 6, -1, 0, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -6, 6, 0, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -6, 6, 0, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -4, 6, 0, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -6, 6, 0, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -6, 6, 0, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -6, 6, 0, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -4, 7, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0.25 ] + [ [ [ -5, 6, -1, 0, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -4, 6, -2, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -5, 6, -1, 0, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -4, 7, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0 ], + [ [ [ -6, 6, 0, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -4, 7, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -6, 6, 0, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -4, 6, 0, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -6, 6, 0, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0 ], + [ [ [ -6, 6, 0, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -6, 6, 0, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -4, 7, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ] ], [ - [ [ [ -6, 6, 0, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -4, 7, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -6, 6, 0, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -6, 6, 0, 1, -2, 2 ], [ -4, 5, 0, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0.25 ] + [ [ [ -6, 6, 0, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -4, 7, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0 ], + [ [ [ -6, 6, 0, 1, -2, 2 ], [ -5, 7, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -6, 6, 0, 1, -2, 2 ], [ -4, 5, 0, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ] ], [ - [ [ [ -6, 6, 0, 1, -2, 2 ], [ -4, 5, 0, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -6, 6, 0, 1, -2, 2 ], [ -5, 6, -1, 2, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -6, 6, -1, 1, -1, 2 ], [ -5, 6, -1, 2, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0.25 ] + [ [ [ -6, 6, 0, 1, -2, 2 ], [ -4, 5, 0, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0 ], + [ [ [ -6, 6, 0, 1, -2, 2 ], [ -5, 6, -1, 2, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0 ], + [ [ [ -6, 6, -1, 1, -1, 2 ], [ -5, 6, -1, 2, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ] ], [ - [ [ [ -6, 7, -1, 1, -2, 2 ], [ -5, 6, -1, 2, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -6, 7, -1, 1, -2, 2 ], [ -5, 7, 0, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0.25 ], - [ [ [ -6, 7, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -5, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0.25 ] + [ [ [ -6, 7, -1, 1, -2, 2 ], [ -5, 6, -1, 2, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0 ], + [ [ [ -6, 7, -1, 1, -2, 2 ], [ -5, 7, 0, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ], + [ [ [ -6, 7, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0 ], + [ [ [ -5, 5, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ] ], [ - [ [ [ -5, 5, -1, 1, -2, 2 ], [ -3, 5, -2, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -5, 6, -1, 1, -2, 2 ] ], 0 ], - [ [ [ -5, 5, -1, 1, -2, 2 ], [ -3, 5, -2, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -4, 5, -2, 1, -2, 2 ] ], 0 ], - [ [ [ -5, 5, -1, 1, -2, 2 ], [ -3, 5, -2, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -4, 5, -2, 1, -2, 2 ] ], 0.25 ], - [ [ [ -5, 5, -1, 1, -2, 2 ], [ -3, 5, -2, 1, -2, 2 ], [ -4, 5, 0, 1, -2, 2 ], [ -4, 5, -2, 1, -2, 2 ] ], 0 ], + [ [ [ -5, 5, -1, 1, -2, 2 ], [ -3, 5, -2, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0 ], + [ [ [ -5, 5, -1, 1, -2, 2 ], [ -3, 5, -2, 1, -2, 2 ], [ -5, 6, 0, 1, -2, 2 ], [ -3, 5, -2, 1, -2, 2 ] ], 0 ], + [ [ [ -5, 5, -1, 1, -2, 2 ], [ -3, 5, -2, 1, -2, 2 ], [ -4, 5, -1, 1, -2, 2 ], [ -3, 5, -2, 1, -2, 2 ] ], 0.25 ], + [ [ [ -5, 5, -1, 1, -2, 2 ], [ -3, 5, -2, 1, -2, 2 ], [ -4, 5, 0, 1, -2, 2 ], [ -3, 5, -2, 1, -2, 2 ] ], 0 ], [ [ [ -5, 5, -1, 1, -2, 2 ], [ -3, 5, -2, 1, -2, 2 ], [ -4, 5, 0, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ], [ [ [ -5, 5, -1, 1, -2, 2 ], [ -3, 5, -2, 1, -2, 2 ], [ -3, 4, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ], [ [ [ -5, 5, -1, 1, -2, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -3, 4, -1, 1, -2, 2 ], [ -4, 6, -1, 1, -2, 2 ] ], 0.25 ] diff --git a/resources/string_quartet_3_rise_coda_only/624f7439/lilypond/part_I.ly b/resources/string_quartet_3_rise_coda_only/624f7439/lilypond/part_I.ly index 7901a68..571d606 100644 --- a/resources/string_quartet_3_rise_coda_only/624f7439/lilypond/part_I.ly +++ b/resources/string_quartet_3_rise_coda_only/624f7439/lilypond/part_I.ly @@ -1,9 +1,9 @@ { { gis2^\markup { \pad-markup #0.2 "-27"} gis''2^\markup { \pad-markup #0.2 "-27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} } \bar "|" - { gis1^\markup { \pad-markup #0.2 "-27"} ~ } + { gis'1^\markup { \pad-markup #0.2 "-27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } \bar "|" - { gis2. ~ gis8[ a8^\markup { \pad-markup #0.2 "-16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] } + { gis'2. ~ gis'8[ a'8^\markup { \pad-markup #0.2 "-16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] } \bar "|" { gis'2^\markup { \pad-markup #0.2 "-27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↑" }} a'8^\markup { \pad-markup #0.2 "-16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 5↓" }}[ g'8^\markup { \pad-markup #0.2 "+19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 11↓" }}] ~ g'4 } \bar "|" diff --git a/resources/string_quartet_3_rise_coda_only/624f7439/lilypond/part_II.ly b/resources/string_quartet_3_rise_coda_only/624f7439/lilypond/part_II.ly index 79346aa..4effe9d 100644 --- a/resources/string_quartet_3_rise_coda_only/624f7439/lilypond/part_II.ly +++ b/resources/string_quartet_3_rise_coda_only/624f7439/lilypond/part_II.ly @@ -1,7 +1,7 @@ { { cis'2^\markup { \pad-markup #0.2 "-29"} gis8^\markup { \pad-markup #0.2 "-27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}[ ais8^\markup { \pad-markup #0.2 "+4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 7↓" }}] c'8^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }}[ cis'8^\markup { \pad-markup #0.2 "-29"}] } \bar "|" - { dis'8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }}[ e'8^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }}] ~ e'2 dis'8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}[ c''8^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] } + { dis'8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↑" }}[ e'8^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }}] ~ e'2 dis''8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}[ c''8^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}] } \bar "|" { cis''8^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }}[ dis''8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}] gis'4^\markup { \pad-markup #0.2 "-27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }} c'4^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }} ~ c'8[ cis'8^\markup { \pad-markup #0.2 "-29"}] } \bar "|" diff --git a/resources/string_quartet_3_rise_coda_only/624f7439/lilypond/part_IV.ly b/resources/string_quartet_3_rise_coda_only/624f7439/lilypond/part_IV.ly index dc2b6a7..ee8b179 100644 --- a/resources/string_quartet_3_rise_coda_only/624f7439/lilypond/part_IV.ly +++ b/resources/string_quartet_3_rise_coda_only/624f7439/lilypond/part_IV.ly @@ -1,7 +1,7 @@ { - { gis,2^\markup { \pad-markup #0.2 "-27"} cis''2^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } + { gis,2^\markup { \pad-markup #0.2 "-27"} cis2^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }} ~ } \bar "|" - { cis''8[ gis'8^\markup { \pad-markup #0.2 "-27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ais,2^\markup { \pad-markup #0.2 "+4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↓" }} c4^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } + { cis8[ gis,8^\markup { \pad-markup #0.2 "-27"}] ais,2^\markup { \pad-markup #0.2 "+4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 7↓" }} c4^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ } \bar "|" { c2 cis8^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↑" }}[ dis8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↑" }}] cis4^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 3↓" }} ~ } \bar "|" diff --git a/resources/string_quartet_3_rise_coda_only/65120e88/65120e88_mus_model.json b/resources/string_quartet_3_rise_coda_only/65120e88/65120e88_mus_model.json index f07d71f..c76bc8b 100644 --- a/resources/string_quartet_3_rise_coda_only/65120e88/65120e88_mus_model.json +++ b/resources/string_quartet_3_rise_coda_only/65120e88/65120e88_mus_model.json @@ -18,14 +18,14 @@ ], [ [ [ [ -7, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ] ], 0 ], - [ [ [ -7, 5, 1, 2, -1, 2 ], [ -6, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ] ], 0 ], - [ [ [ -6, 4, 0, 2, -1, 2 ], [ -6, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ] ], 0.25 ] + [ [ [ -7, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ] ], 0 ], + [ [ [ -6, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ] ], 0.25 ] ], [ - [ [ [ -7, 4, 1, 3, -1, 2 ], [ -6, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ] ], 0 ], - [ [ [ -7, 4, 1, 3, -1, 2 ], [ -6, 4, 1, 3, -1, 1 ], [ -5, 4, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ] ], 0.25 ], - [ [ [ -7, 4, 1, 3, -1, 2 ], [ -6, 3, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ] ], 0 ], - [ [ [ -7, 4, 0, 3, -1, 2 ], [ -6, 3, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ] ], 0.25 ] + [ [ [ -7, 4, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ] ], 0 ], + [ [ [ -7, 4, 1, 3, -1, 2 ], [ -5, 4, 1, 3, -1, 1 ], [ -5, 4, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ] ], 0.25 ], + [ [ [ -7, 4, 1, 3, -1, 2 ], [ -5, 3, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ] ], 0 ], + [ [ [ -7, 4, 0, 3, -1, 2 ], [ -5, 3, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ] ], 0.25 ] ] ] ], diff --git a/resources/string_quartet_3_rise_coda_only/65120e88/lilypond/part_III.ly b/resources/string_quartet_3_rise_coda_only/65120e88/lilypond/part_III.ly index 03337bd..972b1a3 100644 --- a/resources/string_quartet_3_rise_coda_only/65120e88/lilypond/part_III.ly +++ b/resources/string_quartet_3_rise_coda_only/65120e88/lilypond/part_III.ly @@ -1,6 +1,6 @@ { - { cis''4^\markup { \pad-markup #0.2 "-25"} c''4^\markup { \pad-markup #0.2 "-37"} cis''8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }}[ d''8^\markup { \pad-markup #0.2 "+30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}] f8^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}[ fis8^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] } + { cis''4^\markup { \pad-markup #0.2 "-25"} c''4^\markup { \pad-markup #0.2 "-37"} cis''8^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 13↑" }}[ d''8^\markup { \pad-markup #0.2 "+30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}] f'8^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 1↑" }}[ fis'8^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 13↓" }}] } \bar "|" - { g1^\markup { \pad-markup #0.2 "+28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}} + { g'1^\markup { \pad-markup #0.2 "+28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 3↓" }}} \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_3_rise_coda_only/66b20499/66b20499_mus_model.json b/resources/string_quartet_3_rise_coda_only/66b20499/66b20499_mus_model.json index 2a8636b..8e02a12 100644 --- a/resources/string_quartet_3_rise_coda_only/66b20499/66b20499_mus_model.json +++ b/resources/string_quartet_3_rise_coda_only/66b20499/66b20499_mus_model.json @@ -3,27 +3,27 @@ [ [ [ - [ [ [ -4, 4, -1, 2, -1, 2 ], [ -4, 4, -1, 2, -2, 3 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], - [ [ [ -4, 4, -1, 2, -1, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], - [ [ [ -4, 4, -1, 2, -1, 2 ], [ -3, 4, -2, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], - [ [ [ -4, 4, -1, 2, -1, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ] + [ [ [ -5, 4, -1, 2, -1, 2 ], [ -4, 4, -1, 2, -2, 3 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], + [ [ [ -5, 4, -1, 2, -1, 2 ], [ -4, 5, -1, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], + [ [ [ -5, 4, -1, 2, -1, 2 ], [ -3, 4, -2, 2, -2, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ], + [ [ [ -5, 4, -1, 2, -1, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, -1, 2, -2, 2 ] ], 0.25 ] ], [ - [ [ [ -4, 4, -1, 2, -1, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, 0, 1, -1, 2 ] ], 0 ], - [ [ [ -4, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, 0, 1, -1, 2 ] ], 0.25 ], - [ [ [ -4, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -4, 4, 0, 1, -1, 2 ] ], 0.25 ], - [ [ [ -4, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, -1, 2, -1, 2 ], [ -4, 4, 0, 1, -1, 2 ] ], 0.25 ], - [ [ [ -4, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 1, -1, 2 ] ], 0.25 ], - [ [ [ -4, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -6, 5, 0, 2, -1, 2 ], [ -4, 4, 0, 1, -1, 2 ] ], 0.25 ] + [ [ [ -5, 4, -1, 2, -1, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, 0, 1, -1, 2 ] ], 0 ], + [ [ [ -5, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 5, -1, 2, -2, 2 ], [ -4, 4, 0, 1, -1, 2 ] ], 0.25 ], + [ [ [ -5, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -4, 4, 0, 1, -1, 2 ] ], 0.25 ], + [ [ [ -5, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, -1, 2, -1, 2 ], [ -4, 4, 0, 1, -1, 2 ] ], 0.25 ], + [ [ [ -5, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -5, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 1, -1, 2 ] ], 0.25 ], + [ [ [ -5, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -6, 5, 0, 2, -1, 2 ], [ -4, 4, 0, 1, -1, 2 ] ], 0.25 ] ], [ - [ [ [ -4, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -6, 5, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], - [ [ [ -4, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -4, 4, 0, 1, -2, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] + [ [ [ -5, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -6, 5, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], + [ [ [ -5, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -4, 4, 0, 1, -2, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] ], [ - [ [ [ -4, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], - [ [ [ -4, 4, 0, 2, -2, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], - [ [ [ -5, 4, 2, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -5, 4, 0, 2, -2, 2 ], [ -4, 4, 0, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], + [ [ [ -5, 4, 0, 2, -2, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], + [ [ [ -6, 4, 2, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], [ [ [ -6, 4, 1, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], [ [ [ -6, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 3 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], [ [ [ -6, 4, 1, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], diff --git a/resources/string_quartet_3_rise_coda_only/66b20499/lilypond/part_IV.ly b/resources/string_quartet_3_rise_coda_only/66b20499/lilypond/part_IV.ly index 845aaae..5aa7572 100644 --- a/resources/string_quartet_3_rise_coda_only/66b20499/lilypond/part_IV.ly +++ b/resources/string_quartet_3_rise_coda_only/66b20499/lilypond/part_IV.ly @@ -1,7 +1,7 @@ { - { a'2^\markup { \pad-markup #0.2 "-11"} g'2^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↓" }} ~ } + { a2^\markup { \pad-markup #0.2 "-11"} g2^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 11↓" }} ~ } \bar "|" - { g'4 gis'8^\markup { \pad-markup #0.2 "+48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }}[ f8^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ f4 ais,4^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }} ~ } + { g4 gis8^\markup { \pad-markup #0.2 "+48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↑" }}[ f8^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ f4 ais,4^\markup { \pad-markup #0.2 "-40"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 3↓" }} ~ } \bar "|" { ais,2 b,8^\markup { \pad-markup #0.2 "+10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 11↓" }}[ d8^\markup { \pad-markup #0.2 "+30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}] ~ d4 } \bar "|" diff --git a/resources/string_quartet_3_rise_coda_only/736745da/736745da_mus_model.json b/resources/string_quartet_3_rise_coda_only/736745da/736745da_mus_model.json index bf97af4..6a53117 100644 --- a/resources/string_quartet_3_rise_coda_only/736745da/736745da_mus_model.json +++ b/resources/string_quartet_3_rise_coda_only/736745da/736745da_mus_model.json @@ -24,8 +24,8 @@ [ [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ] ], 0 ], [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -6, 4, 1, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -7, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -6, 4, 1, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ] ], 0.25 ] + [ [ [ -6, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -7, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ], [ -5, 5, 1, 2, -1, 2 ] ], 0.25 ] ] ] ], diff --git a/resources/string_quartet_3_rise_coda_only/736745da/lilypond/part_II.ly b/resources/string_quartet_3_rise_coda_only/736745da/lilypond/part_II.ly index 75b08b0..3e4a791 100644 --- a/resources/string_quartet_3_rise_coda_only/736745da/lilypond/part_II.ly +++ b/resources/string_quartet_3_rise_coda_only/736745da/lilypond/part_II.ly @@ -1,6 +1,6 @@ { { ais4^\markup { \pad-markup #0.2 "-40"} gis4^\markup { \pad-markup #0.2 "+48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↑" }} ais8^\markup { \pad-markup #0.2 "+13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super " 1↑" }}[ c'8^\markup { \pad-markup #0.2 "-37"}] cis'8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 5↓" }}[ c'8^\markup { \pad-markup #0.2 "-37"}] } \bar "|" - { f1^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}} + { f'1^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }}} \bar "||" } \ No newline at end of file diff --git a/resources/string_quartet_3_rise_coda_only/767e70f0/767e70f0_mus_model.json b/resources/string_quartet_3_rise_coda_only/767e70f0/767e70f0_mus_model.json index 8421367..1c5521c 100644 --- a/resources/string_quartet_3_rise_coda_only/767e70f0/767e70f0_mus_model.json +++ b/resources/string_quartet_3_rise_coda_only/767e70f0/767e70f0_mus_model.json @@ -3,28 +3,28 @@ [ [ [ - [ [ [ -4, 3, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], - [ [ [ -4, 3, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], - [ [ [ -5, 5, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -5, 5, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -6, 4, 2, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -5, 5, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -6, 4, 1, 2, 0, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], - [ [ [ -5, 5, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -6, 4, 1, 2, 0, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -5, 5, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] + [ [ [ -5, 3, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], + [ [ [ -5, 3, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], + [ [ [ -6, 5, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -6, 5, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -6, 4, 2, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -6, 5, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -6, 4, 1, 2, 0, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], + [ [ [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -6, 4, 1, 2, 0, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] ], [ - [ [ [ -5, 5, 1, 2, -1, 2 ], [ -6, 4, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], - [ [ [ -5, 5, 1, 2, -1, 2 ], [ -6, 4, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -5, 5, 1, 2, -1, 2 ], [ -7, 6, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] + [ [ [ -6, 5, 1, 2, -1, 2 ], [ -6, 4, 1, 2, -1, 2 ], [ -6, 5, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], + [ [ [ -6, 5, 1, 2, -1, 2 ], [ -6, 4, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -6, 5, 1, 2, -1, 2 ], [ -7, 6, 1, 2, -1, 2 ], [ -5, 4, 0, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] ], [ - [ [ [ -5, 5, 1, 2, -1, 2 ], [ -7, 6, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], - [ [ [ -5, 5, 1, 2, -1, 2 ], [ -6, 4, 2, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -4, 4, 0, 2, -1, 2 ], [ -6, 4, 2, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] + [ [ [ -6, 5, 1, 2, -1, 2 ], [ -7, 6, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], + [ [ [ -6, 5, 1, 2, -1, 2 ], [ -6, 4, 2, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -5, 4, 0, 2, -1, 2 ], [ -6, 4, 2, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] ], [ - [ [ [ -6, 4, 1, 4, -1, 2 ], [ -6, 4, 2, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], - [ [ [ -6, 4, 1, 4, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], - [ [ [ -6, 4, 1, 4, -1, 2 ], [ -5, 4, 1, 2, -1, 1 ], [ -6, 4, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], + [ [ [ -7, 4, 1, 4, -1, 2 ], [ -6, 4, 2, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], + [ [ [ -7, 4, 1, 4, -1, 2 ], [ -5, 3, 1, 2, -1, 2 ], [ -6, 4, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ], + [ [ [ -7, 4, 1, 4, -1, 2 ], [ -5, 4, 1, 2, -1, 1 ], [ -6, 4, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0 ], [ [ [ -6, 4, 1, 2, -1, 2 ], [ -5, 4, 1, 2, -1, 1 ], [ -6, 4, 1, 3, -1, 2 ], [ -5, 4, 1, 2, -1, 2 ] ], 0.25 ] ] ] diff --git a/resources/string_quartet_3_rise_coda_only/767e70f0/lilypond/part_IV.ly b/resources/string_quartet_3_rise_coda_only/767e70f0/lilypond/part_IV.ly index 85ee8f1..28f6045 100644 --- a/resources/string_quartet_3_rise_coda_only/767e70f0/lilypond/part_IV.ly +++ b/resources/string_quartet_3_rise_coda_only/767e70f0/lilypond/part_IV.ly @@ -1,6 +1,6 @@ { - { c''2.^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ c''8[ cis''8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }}] } + { c'2.^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super " 1↑" }} ~ c'8[ cis'8^\markup { \pad-markup #0.2 "-25"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 5↓" }}] } \bar "|" - { c''8^\markup { \pad-markup #0.2 "-1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}[ f8^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ f2.} + { c'8^\markup { \pad-markup #0.2 "-1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super " 7↑" }}[ f8^\markup { \pad-markup #0.2 "-38"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super " 1↑" }}] ~ f2.} \bar "||" } \ No newline at end of file