initial commit of seeds and ledgers development code
commit
f67943c010
@ -0,0 +1,481 @@
|
||||
\new StaffGroup \with {\remove "System_start_delimiter_engraver"}
|
||||
<<
|
||||
\new Staff = "I" \with {
|
||||
instrumentName = "I"
|
||||
shortInstrumentName = "I"
|
||||
midiInstrument = #"clarinet"
|
||||
|
||||
}
|
||||
<<
|
||||
|
||||
{
|
||||
\set Score.markFormatter = #format-mark-box-numbers \tempo 2 = 60
|
||||
\numericTimeSignature \time 2/2
|
||||
\clef treble
|
||||
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r2 r16[ e'8.^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "5/4" }}] ~ e'4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e'1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ e'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e'4 ~ e'16[ r8.] r2 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r2. d'4^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "16/11" }} ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ d'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ d'2 dis'4^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "8/5" }} ~ dis'4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis'4 ~ dis'8[ f'8^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "7/4" }}] ~ f'2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f'1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ f'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f'2 ~ f'16[ e'8.^\markup { \pad-markup #0.2 "+13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "11/8" }}] ~ e'4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e'1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ e'4 ~ e'8.[ e'16^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "4/3" }}] ~ e'2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e'8.[ fis'16^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "2/1" }}] ~ fis'2. ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis'1 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ fis'2. ~ fis'8.[ r16] }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r4 r16[ gis'8.^\markup { \pad-markup #0.2 "-5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "3/4" }}] ~ gis'2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis'1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ gis'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis'4 fis'4^\markup { \pad-markup #0.2 "-9"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "2/3" }} ~ fis'2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis'1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ fis'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis'2. ~ fis'8.[ r16] }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r2. r8[ gis'8^\markup { \pad-markup #0.2 "-5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "3/4" }}] ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis'1 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ gis'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis'4 ~ gis'16[ a'8.^\markup { \pad-markup #0.2 "+33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "13/16" }}] ~ a'2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ a'2 ~ a'8[ r8] r4 }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r8.[ ais'16^\markup { \pad-markup #0.2 "-28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "2/1" }}] ~ ais'2. ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ ais'2. r4 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r8.[ ais'16^\markup { \pad-markup #0.2 "-28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "100/100" }}] ~ ais'2. ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'8.[ r16] r2. }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r2 ais'4^\markup { \pad-markup #0.2 "-28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "11/4" }} ~ ais'4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ ais'16[ r8.] r2. }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r2 r8[ ais'8^\markup { \pad-markup #0.2 "-28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "100/100" }}] ~ ais'4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'2. ~ ais'8[ r8] }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r4 ais'4^\markup { \pad-markup #0.2 "-28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "13/4" }} ~ ais'2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'16[ r8.] r2. }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r8.[ a'16^\markup { \pad-markup #0.2 "-22"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "32/13" }}] ~ a'2 ~ a'8.[ g'16^\markup { \pad-markup #0.2 "+49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "16/7" }}] ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g'1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ g'4 ais'4^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "8/3" }} ~ ais'2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ ais'8[ r8] r8[ ais'8^\markup { \pad-markup #0.2 "+16"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "100/100" }}] ~ ais'2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ ais'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais'2 ~ ais'16[ r8.] r4 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 \fermata }>> \bar "|."
|
||||
}
|
||||
|
||||
>>
|
||||
>>
|
@ -0,0 +1,481 @@
|
||||
\new StaffGroup \with {\remove "System_start_delimiter_engraver"}
|
||||
<<
|
||||
\new Staff = "II" \with {
|
||||
instrumentName = "II"
|
||||
shortInstrumentName = "II"
|
||||
midiInstrument = #"clarinet"
|
||||
|
||||
}
|
||||
<<
|
||||
|
||||
{
|
||||
\set Score.markFormatter = #format-mark-box-numbers \tempo 2 = 60
|
||||
\numericTimeSignature \time 2/2
|
||||
\clef treble
|
||||
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r8[ fis'8^\markup { \pad-markup #0.2 "-49"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "11/8" }}] ~ fis'2. ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis'2 ~ fis'8[ e'8^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "16/13" }}] ~ e'4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e'2 f'4^\markup { \pad-markup #0.2 "-2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "4/3" }} ~ f'4 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ f'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f'4 g'4^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "2/1" }} ~ g'2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g'2. r4 }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r4 r8[ f'8^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "7/4" }}] ~ f'2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f'8.[ g'16^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "2/1" }}] ~ g'2. }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ a'4^\markup { \pad-markup #0.2 "+33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "16/7" }} ~ a'2. ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ a'2 ~ a'8.[ r16] r4 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r4 r8.[ b'16^\markup { \pad-markup #0.2 "-39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "2/1" }}] ~ b'2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ b'1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ b'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ b'1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ d''4^\markup { \pad-markup #0.2 "+21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "32/13" }} ~ d''2. ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ d''4 ~ d''16[ cis''8.^\markup { \pad-markup #0.2 "-7"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "16/7" }}] ~ cis''2 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ cis''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis''4 ~ cis''8[ r8] r2 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis''4^\markup { \pad-markup #0.2 "-7"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "100/100" }} ~ cis''2. ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis''1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ cis''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis''1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ cis''2. ~ cis''16[ r8.] }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r4 r16[ cis''8.^\markup { \pad-markup #0.2 "-7"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "100/100" }}] ~ cis''2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis''1 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ cis''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis''1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ cis''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis''2 ~ cis''8.[ d''16^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "5/2" }}] ~ d''4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ d''1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ d''2 dis''4^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "11/4" }} ~ dis''4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis''4 ~ dis''8[ fis''8^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "16/5" }}] ~ fis''2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis''4 f''4^\markup { \pad-markup #0.2 "-26"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "3/1" }} ~ f''2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f''1 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ f''2. ~ f''8[ r8] }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r4 r16[ e''8.^\markup { \pad-markup #0.2 "+21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "16/11" }}] ~ e''2 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis''4^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "11/8" }} ~ dis''2. ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ dis''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis''8.[ fis''16^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "8/5" }}] ~ fis''2. ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis''1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ fis''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis''1 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ fis''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis''2. gis''4^\markup { \pad-markup #0.2 "+7"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "4/1" }} ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis''4 ~ gis''16[ a''8.^\markup { \pad-markup #0.2 "+19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "16/3" }}] ~ a''2 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ a''2. ~ a''16[ ais''8.^\markup { \pad-markup #0.2 "-28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "11/2" }}] ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais''8.[ gis''16^\markup { \pad-markup #0.2 "-19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "64/13" }}] ~ gis''2. ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ gis''4 gis''4^\markup { \pad-markup #0.2 "+7"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "5/1" }} ~ gis''2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis''4 r2. }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r4 r16[ g''8.^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "4/1" }}] ~ g''2 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ g''2 ~ g''8.[ e''16^\markup { \pad-markup #0.2 "+21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "4/1" }}] ~ e''4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e''2 ~ e''8[ d''8^\markup { \pad-markup #0.2 "-10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "7/2" }}] ~ d''4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ d''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ d''1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ d''16[ r8.] r2. }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r2. r8[ d''8^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "5/4" }}] ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ d''2 dis''4^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "11/8" }} ~ dis''4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis''2 ~ dis''8[ e''8^\markup { \pad-markup #0.2 "+21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "4/1" }}] ~ e''4 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ e''2. ~ e''8[ f''8^\markup { \pad-markup #0.2 "-26"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "3/2" }}] ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f''4 fis''4^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "8/5" }} ~ fis''2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis''8[ g''8^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "32/7" }}] ~ g''2. ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ g''2 ~ g''16[ r8.] r4 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r8.[ g''16^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "4/1" }}] ~ g''2. ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g''2 ~ g''8[ fis''8^\markup { \pad-markup #0.2 "-14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "8/5" }}] ~ fis''4 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ fis''2 ~ fis''8[ dis''8^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "11/8" }}] ~ dis''4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis''4 ~ dis''8.[ e''16^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "32/7" }}] ~ e''2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e''2. ~ e''8[ cis''8^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "4/1" }}] ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis''1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ cis''2 b'4^\markup { \pad-markup #0.2 "+1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "7/2" }} ~ b'4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ b'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ b'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ b'1 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ b'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ b'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ b'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ b'4 ~ b'8.[ r16] r2 }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r2 r16[ cis''8.^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "16/5" }}] ~ cis''4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis''1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis''2 ~ cis''8.[ dis''16^\markup { \pad-markup #0.2 "-13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "7/2" }}] ~ dis''4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis''1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ dis''2 ~ dis''16[ r8.] r4 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 \fermata }>> \bar "|."
|
||||
}
|
||||
|
||||
>>
|
||||
>>
|
@ -0,0 +1,481 @@
|
||||
\new StaffGroup \with {\remove "System_start_delimiter_engraver"}
|
||||
<<
|
||||
\new Staff = "III" \with {
|
||||
instrumentName = "III"
|
||||
shortInstrumentName = "III"
|
||||
midiInstrument = #"clarinet"
|
||||
|
||||
}
|
||||
<<
|
||||
|
||||
{
|
||||
\set Score.markFormatter = #format-mark-box-numbers \tempo 2 = 60
|
||||
\numericTimeSignature \time 2/2
|
||||
\clef alto
|
||||
|
||||
<<
|
||||
{ c'4^\markup { \pad-markup #0.2 "+0"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "nil"\normal-size-super "1/1" }} ~ c'2. ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ c'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ c'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ c'1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ c'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ c'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ c'2 ~ c'8.[ r16] r4 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r2. r16[ cis'8.^\markup { \pad-markup #0.2 "-47"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "11/8" }}] ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis'1 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ cis'4 ~ cis'16[ b8.^\markup { \pad-markup #0.2 "-12"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "5/4" }}] ~ b2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ b1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ b1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ b2. a4^\markup { \pad-markup #0.2 "+33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "8/7" }} ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ a4 ~ a8[ b8^\markup { \pad-markup #0.2 "-39"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "16/13" }}] ~ b2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ b1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ b1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ b1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ b1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ b1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ b1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ b1 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ b4 ~ b16[ r8.] r2 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r4 a4^\markup { \pad-markup #0.2 "+6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "2/5" }} ~ a2 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ a4 ~ a8.[ fis16^\markup { \pad-markup #0.2 "+44"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "11/32" }}] ~ fis2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ fis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis4 ~ fis8[ r8] r2 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r2. a4^\markup { \pad-markup #0.2 "+6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "2/5" }} ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ a2. ~ a8[ g8^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "4/11" }}] ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g2 ~ g8[ dis8^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "2/7" }}] ~ dis4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ dis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis2. dis4^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "2/3" }} ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ dis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis2. ~ dis8[ cis8^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "8/13" }}] ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis2. ~ cis8[ r8] }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r2. r16[ c8.^\markup { \pad-markup #0.2 "+4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "2/7" }}] ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ c1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ c1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ c4 ~ c16[ dis8.^\markup { \pad-markup #0.2 "+24"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "1/4" }}] ~ dis2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis8.[ d16^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "5/16" }}] ~ d2. }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis4^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "1/3" }} ~ dis2. }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ c4^\markup { \pad-markup #0.2 "+4"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "2/7" }} ~ c2. ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ c4 c4^\markup { \pad-markup #0.2 "+35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "2/11" }} ~ c2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ c2 ~ c16[ d8.^\markup { \pad-markup #0.2 "+27"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "13/64" }}] ~ d4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ d2 ~ d8[ dis8^\markup { \pad-markup #0.2 "-29"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "1/3" }}] ~ dis4 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ dis4 ~ dis16[ e8.^\markup { \pad-markup #0.2 "+21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "4/11" }}] ~ e2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e8[ r8] r4 r16[ e8.^\markup { \pad-markup #0.2 "+21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "100/100" }}] ~ e4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ e2. ~ e8.[ r16] }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r4 e4^\markup { \pad-markup #0.2 "+21"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "100/100" }} ~ e2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ e1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ e8[ r8] r2. }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r2 r8[ cis8^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "4/13" }}] ~ cis4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ cis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ cis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis2 ~ cis16[ f8.^\markup { \pad-markup #0.2 "-26"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "3/8" }}] ~ f4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f4 ~ f8.[ dis16^\markup { \pad-markup #0.2 "-13"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "5/16" }}] ~ dis2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis8.[ fis16^\markup { \pad-markup #0.2 "+3"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "3/8" }}] ~ fis2. }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ g4^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "2/5" }} ~ g4 ~ g8.[ ais16^\markup { \pad-markup #0.2 "-28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "1/2" }}] ~ ais4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais4 ~ ais16[ b8.^\markup { \pad-markup #0.2 "+1"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "1/2" }}] ~ b2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ b16[ cis'8.^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "4/7" }}] ~ cis'2. ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis'2. ~ cis'8[ r8] }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ d'4^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "13/8" }} ~ d'2. ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ d'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ d'2 ~ d'8[ cis'8^\markup { \pad-markup #0.2 "+32"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "8/5" }}] ~ cis'4 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ cis'1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ cis'4 ~ cis'8[ d'8^\markup { \pad-markup #0.2 "-41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "13/8" }}] ~ d'2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ d'8[ c'8^\markup { \pad-markup #0.2 "-33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "16/11" }}] ~ c'2. ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ c'8[ r8] r2. }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 \fermata }>> \bar "|."
|
||||
}
|
||||
|
||||
>>
|
||||
>>
|
@ -0,0 +1,481 @@
|
||||
\new StaffGroup \with {\remove "System_start_delimiter_engraver"}
|
||||
<<
|
||||
\new Staff = "IV" \with {
|
||||
instrumentName = "IV"
|
||||
shortInstrumentName = "IV"
|
||||
midiInstrument = #"clarinet"
|
||||
|
||||
}
|
||||
<<
|
||||
|
||||
{
|
||||
\set Score.markFormatter = #format-mark-box-numbers \tempo 2 = 60
|
||||
\numericTimeSignature \time 2/2
|
||||
\clef bass
|
||||
|
||||
<<
|
||||
{ r2 r8[ gis8^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "4/5" }}] ~ gis4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ gis2 ~ gis16[ g8.^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "3/4" }}] ~ g4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g8.[ r16] r2. }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r8.[ g16^\markup { \pad-markup #0.2 "+2"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "1/1" }}] ~ g2. ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g1 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ g1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ g1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g2. ~ g8.[ f16^\markup { \pad-markup #0.2 "+10"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "8/11" }}] ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f4 ~ f8[ fis8^\markup { \pad-markup #0.2 "-37"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "3/4" }}] ~ fis2 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ fis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis1 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ fis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis2 ~ fis16[ r8.] r4 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r2. r8[ gis8^\markup { \pad-markup #0.2 "-5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "1/2" }}] ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ gis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis4 ~ gis8.[ a16^\markup { \pad-markup #0.2 "+33"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "13/32" }}] ~ a2 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ a1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ a4 ~ a16[ g8.^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "4/11" }}] ~ g2 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ g8.[ fis16^\markup { \pad-markup #0.2 "-9"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "1/2" }}] ~ fis2. ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis2 ~ fis8[ r8] r4 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r8.[ gis16^\markup { \pad-markup #0.2 "-5"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "1/2" }}] ~ gis2. ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ gis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis4 g2.^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "4/11" }} ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ g2. ~ g8[ a8^\markup { \pad-markup #0.2 "+6"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "II"\normal-size-super "2/5" }}] ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ a2 ~ a8.[ ais16^\markup { \pad-markup #0.2 "-28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "16/11" }}] ~ ais4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ ais1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais1 ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ ais4 ~ ais16[ r8.] r2 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r8.[ gis16^\markup { \pad-markup #0.2 "+7"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "5/4" }}] ~ gis2. ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ gis1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ gis16[ g8.^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "8/7" }}] ~ g2. ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g2. ~ g8[ a8^\markup { \pad-markup #0.2 "+19"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "4/3" }}] ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ a1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ a1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ a1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ a2 r2 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r8[ g8^\markup { \pad-markup #0.2 "-48"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "8/7" }}] ~ g2. ~ }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ g1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g2 ~ g8.[ ais16^\markup { \pad-markup #0.2 "-28"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "11/8" }}] ~ ais4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ ais1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ ais2 r2 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r2. r8[ g8^\markup { \pad-markup #0.2 "+41"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "7/16" }}] ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ g1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ g2 ~ g16[ fis8.^\markup { \pad-markup #0.2 "+30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "4/3" }}] ~ fis4 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis2. ~ fis16[ f8.^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "III"\normal-size-super "5/4" }}] ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ f1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f2 ~ f8.[ r16] r4 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ r4 f2.^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "IV"\normal-size-super "1/1" }} ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f1 ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ f1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f2 ~ f8.[ r16] r4 }
|
||||
>>
|
||||
\bar "|" \pageBreak
|
||||
<<
|
||||
{ r2 fis2^\markup { \pad-markup #0.2 "+30"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "2/5" }} ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ fis2. ~ fis8[ f8^\markup { \pad-markup #0.2 "-35"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "4/11" }}] ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f1 ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ f4 f2.^\markup { \pad-markup #0.2 "+18"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "3/8" }} ~ }
|
||||
>>
|
||||
\bar "|" \break \noPageBreak
|
||||
<<
|
||||
{ f8.[ dis16^\markup { \pad-markup #0.2 "+14"}_\markup { \lower #3 \pad-markup #0.2 \concat{ "I"\normal-size-super "1/3" }}] ~ dis2. ~ }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ dis8.[ r16] r2. }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 }
|
||||
>>
|
||||
\bar "|"
|
||||
<<
|
||||
{ r1 \fermata }>> \bar "|."
|
||||
}
|
||||
|
||||
>>
|
||||
>>
|
@ -0,0 +1,177 @@
|
||||
\version "2.22.2"
|
||||
|
||||
#(define (override-color-for-all-grobs color)
|
||||
(lambda (context)
|
||||
(let loop ((x all-grob-descriptions))
|
||||
(if (not (null? x))
|
||||
(let ((grob-name (caar x)))
|
||||
(ly:context-pushpop-property context grob-name 'color color)
|
||||
(loop (cdr x)))))))
|
||||
|
||||
#(define-markup-command (relMark layout props mus) (ly:music?)
|
||||
#:properties ((size -2))
|
||||
(interpret-markup layout props
|
||||
#{
|
||||
\markup {
|
||||
\score {
|
||||
\new Staff { $mus }
|
||||
\layout {
|
||||
\context {
|
||||
\Staff
|
||||
\remove Time_signature_engraver
|
||||
fontSize = #-2
|
||||
\hide Stem
|
||||
\override TextScript.outside-staff-priority = ##f
|
||||
\override StaffSymbol.staff-space = #(magstep -2)
|
||||
\override StaffSymbol.thickness = #(magstep -2)
|
||||
\override TextScript.self-alignment-X = #-0.4
|
||||
\override TextScript.staff-padding = #1
|
||||
}
|
||||
\context {
|
||||
\Score
|
||||
proportionalNotationDuration = #(ly:make-moment 1/16)
|
||||
\remove "Separating_line_group_engraver"
|
||||
\override SpacingSpanner.strict-note-spacing = ##t
|
||||
\override RehearsalMark.self-alignment-X = #-1
|
||||
\override RehearsalMark.Y-offset = #10
|
||||
\override RehearsalMark.X-offset = #10
|
||||
}
|
||||
\context {
|
||||
\Voice
|
||||
\consists "Horizontal_bracket_engraver"
|
||||
\override HorizontalBracket.direction = #UP
|
||||
}
|
||||
indent = 0
|
||||
line-width = 4\cm
|
||||
}
|
||||
}
|
||||
}
|
||||
#}))
|
||||
|
||||
|
||||
\paper {
|
||||
#(set-paper-size "a4" 'portrait)
|
||||
top-margin = 1 \cm
|
||||
bottom-margin = 1 \cm
|
||||
left-margin = 2 \cm
|
||||
ragged-bottom = ##t
|
||||
|
||||
top-system-spacing =
|
||||
#'((basic-distance . 15 )
|
||||
(minimum-distance . 15 )
|
||||
(padding . 0 )
|
||||
(stretchability . 0))
|
||||
|
||||
system-system-spacing =
|
||||
#'((basic-distance . 35 )
|
||||
(minimum-distance . 35 )
|
||||
(padding . 0 )
|
||||
(stretchability . 0))
|
||||
|
||||
last-bottom-spacing =
|
||||
#'((basic-distance . 10 )
|
||||
(minimum-distance . 10 )
|
||||
(padding . 0 )
|
||||
(stretchability . 0))
|
||||
|
||||
%systems-per-page = 3
|
||||
first-page-number = 1
|
||||
print-first-page-number = ##t
|
||||
|
||||
print-page-number = ##t
|
||||
oddHeaderMarkup = \markup { \fill-line { \line { \on-the-fly #not-first-page {\pad-markup #2 { \concat {\italic {"test"}}}}}}}
|
||||
evenHeaderMarkup = \markup { \fill-line { \line { \on-the-fly #not-first-page {\pad-markup #2 { \concat {\italic {"test"}}}}}}}
|
||||
oddFooterMarkup = \markup { \fill-line {
|
||||
\concat {
|
||||
"-"
|
||||
\fontsize #1.5
|
||||
\on-the-fly #print-page-number-check-first
|
||||
\fromproperty #'page:page-number-string
|
||||
"-"}}}
|
||||
evenFooterMarkup = \markup { \fill-line {
|
||||
\concat {
|
||||
"-"
|
||||
\fontsize #1.5
|
||||
\on-the-fly #print-page-number-check-first
|
||||
\fromproperty #'page:page-number-string
|
||||
"-"}}}
|
||||
}
|
||||
|
||||
\header {
|
||||
title = \markup { \italic {test}}
|
||||
composer = \markup \right-column {"michael winter" "(berlin & mexico city; 2023)"}
|
||||
%poet = "seed: xxx"
|
||||
tagline = ""
|
||||
}
|
||||
|
||||
#(set-global-staff-size 11)
|
||||
|
||||
\layout {
|
||||
indent = 0.0\cm
|
||||
line-width = 17.5\cm
|
||||
ragged-last = ##f
|
||||
ragged-right = ##f
|
||||
|
||||
\context {
|
||||
\Score
|
||||
\override BarNumber.stencil = #(make-stencil-circler 0.1 0.25 ly:text-interface::print)
|
||||
\override Stem.stemlet-length = #0.75
|
||||
proportionalNotationDuration = #(ly:make-moment 1/16)
|
||||
\remove "Separating_line_group_engraver"
|
||||
\override RehearsalMark.self-alignment-X = #-1
|
||||
\override RehearsalMark.Y-offset = #10
|
||||
\override RehearsalMark.X-offset = #-8
|
||||
%\override RehearsalMark.outside-staff-priority = #0
|
||||
}
|
||||
\context {
|
||||
\Staff
|
||||
|
||||
\override VerticalAxisGroup.staff-staff-spacing =
|
||||
#'((basic-distance . 20 )
|
||||
(minimum-distance . 20 )
|
||||
(padding . 0 )
|
||||
(stretchability . 0))
|
||||
|
||||
\override VerticalAxisGroup.default-staff-staff-spacing =
|
||||
#'((basic-distance . 20 )
|
||||
(minimum-distance . 20 )
|
||||
(padding . 0 )
|
||||
(stretchability . 0))
|
||||
\override TextScript.staff-padding = #2
|
||||
\override TextScript.self-alignment-X = #0
|
||||
}
|
||||
\context {
|
||||
\StaffGroup
|
||||
\name "SemiStaffGroup"
|
||||
\consists "Span_bar_engraver"
|
||||
\override SpanBar.stencil =
|
||||
#(lambda (grob)
|
||||
(if (string=? (ly:grob-property grob 'glyph-name) "|")
|
||||
(set! (ly:grob-property grob 'glyph-name) ""))
|
||||
(ly:span-bar::print grob))
|
||||
}
|
||||
\context {
|
||||
\Score
|
||||
\accepts SemiStaffGroup
|
||||
}
|
||||
}
|
||||
|
||||
\midi { }
|
||||
|
||||
|
||||
\score{
|
||||
\new Score
|
||||
<<
|
||||
\new SemiStaffGroup {
|
||||
<<
|
||||
\include "includes/part_I.ly"
|
||||
\include "includes/part_II.ly"
|
||||
\include "includes/part_III.ly"
|
||||
\include "includes/part_IV.ly"
|
||||
>>
|
||||
}
|
||||
>>
|
||||
|
||||
\layout{}
|
||||
\midi{}
|
||||
}
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,159 @@
|
||||
{
|
||||
"version": "1.24.0",
|
||||
"createdWith": "Open Stage Control",
|
||||
"type": "fragment",
|
||||
"content": {
|
||||
"type": "panel",
|
||||
"top": 0,
|
||||
"left": 0,
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_probs",
|
||||
"visible": true,
|
||||
"interaction": true,
|
||||
"comments": "",
|
||||
"width": "100%",
|
||||
"height": "100%",
|
||||
"expand": "false",
|
||||
"colorText": "auto",
|
||||
"colorWidget": "auto",
|
||||
"colorStroke": "auto",
|
||||
"colorFill": "auto",
|
||||
"alphaStroke": "auto",
|
||||
"alphaFillOff": "auto",
|
||||
"alphaFillOn": "auto",
|
||||
"lineWidth": "auto",
|
||||
"borderRadius": "auto",
|
||||
"padding": "auto",
|
||||
"html": "",
|
||||
"css": "",
|
||||
"colorBg": "auto",
|
||||
"layout": "default",
|
||||
"justify": "start",
|
||||
"gridTemplate": "",
|
||||
"contain": true,
|
||||
"scroll": true,
|
||||
"innerPadding": true,
|
||||
"variables": "@{parent.variables}",
|
||||
"traversing": false,
|
||||
"value": "",
|
||||
"default": "",
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"typeTags": "",
|
||||
"decimals": 2,
|
||||
"target": "",
|
||||
"ignoreDefaults": false,
|
||||
"bypass": false,
|
||||
"onCreate": "",
|
||||
"onValue": "",
|
||||
"widgets": [
|
||||
{
|
||||
"type": "fragment",
|
||||
"top": 0,
|
||||
"left": 0,
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_dur",
|
||||
"visible": true,
|
||||
"interaction": true,
|
||||
"comments": "",
|
||||
"width": "auto",
|
||||
"height": "100%",
|
||||
"expand": "false",
|
||||
"css": ":host {\n\n width: calc(100% - 160rem);\n\n}",
|
||||
"file": "fragments/env.json",
|
||||
"fallback": "",
|
||||
"props": {
|
||||
"variables": {
|
||||
"grandparent": "@{parent.id}"
|
||||
}
|
||||
},
|
||||
"address": "auto",
|
||||
"variables": "@{parent.variables}"
|
||||
},
|
||||
{
|
||||
"type": "fragment",
|
||||
"top": 0,
|
||||
"left": "auto",
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_chord",
|
||||
"visible": true,
|
||||
"interaction": true,
|
||||
"comments": "",
|
||||
"width": 80,
|
||||
"height": "100%",
|
||||
"expand": "false",
|
||||
"css": ":host {\n\n left: calc(100% - 160rem);\n\n}",
|
||||
"file": "fragments/slider.json",
|
||||
"fallback": "",
|
||||
"props": {
|
||||
"variables": {
|
||||
"min": 0,
|
||||
"max": 1,
|
||||
"slider_label": "chord prob",
|
||||
"grandparent": "@{parent.id}"
|
||||
}
|
||||
},
|
||||
"address": "auto",
|
||||
"variables": "@{parent.variables}"
|
||||
},
|
||||
{
|
||||
"type": "variable",
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_vals",
|
||||
"comments": "",
|
||||
"value": "",
|
||||
"default": [
|
||||
0,
|
||||
0.25,
|
||||
2,
|
||||
0,
|
||||
0.5,
|
||||
0.5,
|
||||
0.5,
|
||||
1,
|
||||
0.5
|
||||
],
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"typeTags": "",
|
||||
"decimals": 2,
|
||||
"target": "",
|
||||
"ignoreDefaults": false,
|
||||
"bypass": false,
|
||||
"onCreate": "",
|
||||
"onValue": "var sync = get(getProp(\"parent\", \"id\") + \"_sync\");\nvar pID = getProp(\"parent\", \"id\");\nif(sync == \"entrances\") {\n pID = \"entrances_probs\"\n} else \nif (sync == \"passages\") {\n pID = \"passages_probs\"\n} else \nif (sync == \"exits\") {\n pID = \"exits_probs\"\n}\n\nvar cProb = get(pID + '_chord_val_slider')\nvar pRange = get(pID + '_pad_val_rslider')\nvar env = get(pID + '_dur_env_vals')\nvalue = ([cProb]).concat(pRange).concat(env);\nset(\"this\", value)"
|
||||
},
|
||||
{
|
||||
"type": "fragment",
|
||||
"top": 0,
|
||||
"left": "auto",
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_pad",
|
||||
"visible": true,
|
||||
"interaction": true,
|
||||
"comments": "",
|
||||
"width": 80,
|
||||
"height": "100%",
|
||||
"expand": "false",
|
||||
"css": ":host {\n\n left: calc(100% - 80rem);\n\n}",
|
||||
"file": "fragments/range_slider.json",
|
||||
"fallback": "",
|
||||
"props": {
|
||||
"variables": {
|
||||
"min": 0,
|
||||
"max": 10,
|
||||
"rslider_label": "pad",
|
||||
"grandparent": "@{parent.id}",
|
||||
"decimals": 2
|
||||
}
|
||||
},
|
||||
"address": "auto",
|
||||
"variables": "@{parent.variables}"
|
||||
}
|
||||
],
|
||||
"tabs": [],
|
||||
"tabsPosition": "top"
|
||||
}
|
||||
}
|
@ -0,0 +1,372 @@
|
||||
{
|
||||
"version": "1.22.0",
|
||||
"createdWith": "Open Stage Control",
|
||||
"type": "fragment",
|
||||
"content": {
|
||||
"type": "panel",
|
||||
"top": 90,
|
||||
"left": 160,
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_env",
|
||||
"visible": true,
|
||||
"interaction": true,
|
||||
"comments": "",
|
||||
"width": 440,
|
||||
"height": 310,
|
||||
"expand": "false",
|
||||
"colorText": "auto",
|
||||
"colorWidget": "auto",
|
||||
"colorStroke": "auto",
|
||||
"colorFill": "auto",
|
||||
"alphaStroke": "auto",
|
||||
"alphaFillOff": "auto",
|
||||
"alphaFillOn": "auto",
|
||||
"lineWidth": "auto",
|
||||
"borderRadius": "auto",
|
||||
"padding": "auto",
|
||||
"html": "",
|
||||
"css": "",
|
||||
"colorBg": "auto",
|
||||
"layout": "default",
|
||||
"justify": "start",
|
||||
"gridTemplate": "",
|
||||
"contain": true,
|
||||
"scroll": true,
|
||||
"innerPadding": true,
|
||||
"verticalTabs": false,
|
||||
"variables": "@{parent.variables}",
|
||||
"traversing": false,
|
||||
"value": "",
|
||||
"default": "",
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"typeTags": "",
|
||||
"decimals": 2,
|
||||
"target": "",
|
||||
"ignoreDefaults": false,
|
||||
"bypass": false,
|
||||
"onCreate": "",
|
||||
"onValue": "",
|
||||
"widgets": [
|
||||
{
|
||||
"type": "variable",
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_vals",
|
||||
"comments": "",
|
||||
"value": "",
|
||||
"default": [
|
||||
[
|
||||
0,
|
||||
0.5
|
||||
],
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
],
|
||||
[
|
||||
1,
|
||||
0.5
|
||||
]
|
||||
],
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"typeTags": "",
|
||||
"decimals": 2,
|
||||
"target": "",
|
||||
"ignoreDefaults": false,
|
||||
"bypass": false,
|
||||
"onCreate": "",
|
||||
"onValue": ""
|
||||
},
|
||||
{
|
||||
"type": "canvas",
|
||||
"top": 30,
|
||||
"left": 0,
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_canvas",
|
||||
"visible": true,
|
||||
"interaction": true,
|
||||
"comments": "",
|
||||
"width": "auto",
|
||||
"height": "auto",
|
||||
"expand": "false",
|
||||
"colorText": "auto",
|
||||
"colorWidget": "auto",
|
||||
"colorStroke": "auto",
|
||||
"colorFill": "auto",
|
||||
"alphaStroke": "auto",
|
||||
"alphaFillOff": "auto",
|
||||
"alphaFillOn": "auto",
|
||||
"lineWidth": "auto",
|
||||
"borderRadius": "auto",
|
||||
"padding": "auto",
|
||||
"html": "",
|
||||
"css": ":host {\n\n width: 100%;\n height: calc(100% - 70rem);\n\n}",
|
||||
"valueLength": 64,
|
||||
"autoClear": true,
|
||||
"continuous": false,
|
||||
"value": "",
|
||||
"default": "",
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"typeTags": "",
|
||||
"decimals": 2,
|
||||
"target": "",
|
||||
"ignoreDefaults": false,
|
||||
"bypass": false,
|
||||
"onCreate": "set(getProp(\"parent\", \"id\") + \"_size\", 3)\nvalue[0] = [0.0, 0.5]\nvalue[1] = [0.5, 0.5]\nvalue[2] = [1.0, 0.5]\n\nlocals.eucDistance = function(p1, p2) {\n var a = p1[0] - p2[0];\n var b = p1[1] - (1 - p2[1]);\n return Math.sqrt( a*a + b*b );\n}\n\nlocals.closest = function(v, x, y, s){\n return (v.slice(0, s).reduce((a, b) => \n locals.eucDistance([x, y], a) < locals.eucDistance([x, y], b) ? a : b));\n}\n\nlocals.cIndex = 1\nlocals.cDist = 0\n\nsetVar(this, 'reset', function() {\n set(getProp(\"parent\", \"id\") + \"_size\", 3)\n var val = []\n val.length = 64; \n val.fill(0);\n val[0] = [0.0, 0.5]\n val[1] = [0.5, 0.5]\n val[2] = [1.0, 0.5]\n set(getProp(\"parent\", \"id\") + '_canvas', val)\n})\n\n\nsetVar(this, 'update', function() {\n var limits = get(getProp(\"parent\", \"id\") + '_rslider')\n var vals = get(getProp(\"parent\", \"id\") + '_canvas')\n var size = get(getProp(\"parent\", \"id\") + '_size')\n set(getProp(\"parent\", \"id\") + \"_vals\", (limits).concat(vals.slice(0, size).flat()));\n var parentVariables = getProp('parent', 'variables')\n if (parentVariables.grandparent) {\n set(parentVariables.grandparent + '_vals', value)\n }\n})\n",
|
||||
"onValue": "// apply limits\nfor(var i = 0; i < get(getProp(\"parent\", \"id\") + \"_size\"); i += 1) {\n if(typeof value[i] === 'string') {value[i] = JSON.parse(value[i])}\n value[i] = [Math.max(0, Math.min(1, value[i][0])), Math.max(0, Math.min(1, value[i][1]))]\n}\n\n// re-update widget value without retriggering script or sending message\nset(\"this\", value, {sync: true, send: false})\ngetVar('this', 'update')()",
|
||||
"onTouch": "var lock = false\n\n// store normalized coordinates\nif (event.type == \"start\") {\n locals.x = event.offsetX / width\n locals.y = event.offsetY / height\n lock = true\n locals.cIndex = value.indexOf(locals.closest(value, locals.x, locals.y, get(getProp(\"parent\", \"id\") + \"_size\")))\n locals.cDist = locals.eucDistance([locals.x, locals.y], value[locals.cIndex])\n} else {\n // when the pointer is moving, increment coordinates\n // because offsetX and offsetY may not be relevant\n // if the pointer hovers a different widgets\n locals.x += event.movementX / width\n locals.y += event.movementY / height\n}\n\n\nif(lock && (locals.cDist > 0.1) && (locals.x >= 0) && (locals.y >= 0) && (locals.x <= 1) && (locals.y <= 1)) {\n value[get(getProp(\"parent\", \"id\") + \"_size\")] = [locals.x, 1 - locals.y]\n value.sort((a, b) => a[0] - b[0])\n locals.cIndex = value.indexOf(locals.closest(value, locals.x, locals.y, get(getProp(\"parent\", \"id\") + \"_size\")))\n set(getProp(\"parent\", \"id\") + '_size', get(getProp(\"parent\", \"id\") + \"_size\") + 1)\n} else {\n value[locals.cIndex] = [locals.x, 1 - locals.y]\n}\n\nvar min = get(getProp(\"parent\", \"id\") + \"_input_min\")\nvar max = get(getProp(\"parent\", \"id\") + \"_input_max\")\n\nif (event.type != \"stop\") {\n set(getProp(\"parent\", \"id\") + \"_mpos\", \"x: \" + ((locals.x * (max - min)) + min).toFixed(2) + \"\\ny: \" + (1 - locals.y).toFixed(2))\n} else {\n lock = false\n set(getProp(\"parent\", \"id\") + \"_mpos\", \"\")\n}\nset(\"this\", value)",
|
||||
"onDraw": "//var size = get('@{parent.id}_size')\nfor(var i = 0; i < get(getProp(\"parent\", \"id\") + \"_size\"); i += 1) {\n ctx.fillStyle = cssVars.colorFill\n ctx.fillRect(value[i][0] * width - 2.5, (1 - value[i][1]) * height - 2.5, 5, 5)\n}\n\nctx.stroke();\nctx.strokeStyle = cssVars.colorFill\nctx.beginPath();\n\nfor(var i = 0; i < get(getProp(\"parent\", \"id\") + \"_size\"); i += 1) {\n if(i === 0){\n ctx.moveTo(value[i][0] * width, (1 - value[i][1]) * height)\n } else {\n ctx.lineTo(value[i][0] * width, (1 - value[i][1]) * height); // Draw a line to (150, 100)\n }\n}\n\nctx.stroke();",
|
||||
"onResize": ""
|
||||
},
|
||||
{
|
||||
"type": "variable",
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_size",
|
||||
"comments": "",
|
||||
"value": "",
|
||||
"default": 3,
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"typeTags": "",
|
||||
"decimals": 2,
|
||||
"target": "",
|
||||
"ignoreDefaults": false,
|
||||
"bypass": false,
|
||||
"onCreate": "",
|
||||
"onValue": ""
|
||||
},
|
||||
{
|
||||
"type": "button",
|
||||
"top": "auto",
|
||||
"left": 0,
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_flatten",
|
||||
"visible": true,
|
||||
"interaction": true,
|
||||
"comments": "",
|
||||
"width": 30,
|
||||
"height": 30,
|
||||
"expand": "false",
|
||||
"colorText": "auto",
|
||||
"colorWidget": "auto",
|
||||
"colorStroke": "auto",
|
||||
"colorFill": "auto",
|
||||
"alphaStroke": "auto",
|
||||
"alphaFillOff": "auto",
|
||||
"alphaFillOn": "auto",
|
||||
"lineWidth": "auto",
|
||||
"borderRadius": "auto",
|
||||
"padding": "auto",
|
||||
"html": "",
|
||||
"css": ":host {\n\n top: calc(100% - 30rem);\n\n}",
|
||||
"colorTextOn": "auto",
|
||||
"label": "F",
|
||||
"vertical": false,
|
||||
"wrap": false,
|
||||
"on": 1,
|
||||
"off": 0,
|
||||
"mode": "push",
|
||||
"doubleTap": false,
|
||||
"decoupled": false,
|
||||
"value": "",
|
||||
"default": "",
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"typeTags": "",
|
||||
"decimals": 2,
|
||||
"target": "",
|
||||
"ignoreDefaults": false,
|
||||
"bypass": false,
|
||||
"onCreate": "",
|
||||
"onValue": "if(value === 1){\n getVar(getProp(\"parent\", \"id\") + '_canvas', 'reset')()\n}"
|
||||
},
|
||||
{
|
||||
"type": "range",
|
||||
"top": 0,
|
||||
"left": 50,
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_rslider",
|
||||
"visible": true,
|
||||
"interaction": true,
|
||||
"comments": "",
|
||||
"width": "auto",
|
||||
"height": 30,
|
||||
"expand": "false",
|
||||
"colorText": "auto",
|
||||
"colorWidget": "auto",
|
||||
"colorStroke": "auto",
|
||||
"colorFill": "auto",
|
||||
"alphaStroke": "auto",
|
||||
"alphaFillOff": "auto",
|
||||
"alphaFillOn": "auto",
|
||||
"lineWidth": "auto",
|
||||
"borderRadius": "auto",
|
||||
"padding": "auto",
|
||||
"html": "",
|
||||
"css": ":host {\n\n width: calc(100% - 100rem);\n\n}",
|
||||
"design": "default",
|
||||
"knobSize": "auto",
|
||||
"horizontal": true,
|
||||
"pips": false,
|
||||
"dashed": false,
|
||||
"gradient": [],
|
||||
"snap": true,
|
||||
"spring": false,
|
||||
"doubleTap": false,
|
||||
"range": {
|
||||
"min": 0,
|
||||
"max": 5
|
||||
},
|
||||
"logScale": false,
|
||||
"sensitivity": 1,
|
||||
"steps": "",
|
||||
"value": "[@{@{parent.id}_input_min.value}, @{@{parent.id}_input_max.value}]",
|
||||
"default": [
|
||||
0.5,
|
||||
2
|
||||
],
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"typeTags": "",
|
||||
"decimals": 2,
|
||||
"target": "",
|
||||
"ignoreDefaults": false,
|
||||
"bypass": false,
|
||||
"onCreate": "",
|
||||
"onValue": "getVar(getProp(\"parent\", \"id\") + '_canvas', 'update')()",
|
||||
"onTouch": ""
|
||||
},
|
||||
{
|
||||
"type": "input",
|
||||
"top": 0,
|
||||
"left": "auto",
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_input_max",
|
||||
"visible": true,
|
||||
"interaction": true,
|
||||
"comments": "",
|
||||
"width": 50,
|
||||
"height": "auto",
|
||||
"expand": "false",
|
||||
"colorText": "auto",
|
||||
"colorWidget": "auto",
|
||||
"colorStroke": "auto",
|
||||
"colorFill": "auto",
|
||||
"alphaStroke": "auto",
|
||||
"alphaFillOff": "auto",
|
||||
"alphaFillOn": "auto",
|
||||
"lineWidth": "auto",
|
||||
"borderRadius": "auto",
|
||||
"padding": "auto",
|
||||
"html": "",
|
||||
"css": ":host {\n\n left: calc(100% - 50rem);\n\n}",
|
||||
"align": "center",
|
||||
"unit": "",
|
||||
"asYouType": false,
|
||||
"numeric": false,
|
||||
"validation": "",
|
||||
"maxLength": "",
|
||||
"value": "@{@{parent.id}_rslider.value.1}",
|
||||
"default": "",
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"typeTags": "",
|
||||
"decimals": 2,
|
||||
"target": "",
|
||||
"ignoreDefaults": false,
|
||||
"bypass": true,
|
||||
"onCreate": "",
|
||||
"onValue": ""
|
||||
},
|
||||
{
|
||||
"type": "input",
|
||||
"top": 0,
|
||||
"left": 0,
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_input_min",
|
||||
"visible": true,
|
||||
"comments": "",
|
||||
"width": 50,
|
||||
"height": "auto",
|
||||
"expand": "false",
|
||||
"colorText": "auto",
|
||||
"colorWidget": "auto",
|
||||
"colorStroke": "auto",
|
||||
"colorFill": "auto",
|
||||
"alphaStroke": "auto",
|
||||
"alphaFillOff": "auto",
|
||||
"alphaFillOn": "auto",
|
||||
"lineWidth": "auto",
|
||||
"borderRadius": "auto",
|
||||
"padding": "auto",
|
||||
"html": "",
|
||||
"css": "",
|
||||
"align": "center",
|
||||
"value": "@{@{parent.id}_rslider.value.0}",
|
||||
"default": "",
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"decimals": 2,
|
||||
"target": "",
|
||||
"onCreate": "",
|
||||
"onValue": "",
|
||||
"interaction": true,
|
||||
"unit": "",
|
||||
"asYouType": false,
|
||||
"numeric": false,
|
||||
"validation": "",
|
||||
"maxLength": "",
|
||||
"typeTags": "",
|
||||
"ignoreDefaults": false,
|
||||
"bypass": true
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"top": "auto",
|
||||
"left": "auto",
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_mpos",
|
||||
"visible": true,
|
||||
"comments": "",
|
||||
"width": 130,
|
||||
"height": 40,
|
||||
"expand": "false",
|
||||
"colorText": "auto",
|
||||
"colorWidget": "auto",
|
||||
"colorStroke": "auto",
|
||||
"colorFill": "auto",
|
||||
"alphaStroke": "auto",
|
||||
"alphaFillOff": "auto",
|
||||
"alphaFillOn": "auto",
|
||||
"lineWidth": "auto",
|
||||
"borderRadius": "auto",
|
||||
"padding": "auto",
|
||||
"html": "",
|
||||
"css": ":host {\n\n top: calc(100% - 40rem);\n left: calc(50% - 65rem);\n\n}",
|
||||
"align": "center",
|
||||
"value": "",
|
||||
"default": "",
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"decimals": 2,
|
||||
"target": "",
|
||||
"onCreate": "",
|
||||
"onValue": "",
|
||||
"vertical": false,
|
||||
"wrap": false
|
||||
}
|
||||
],
|
||||
"tabs": []
|
||||
}
|
||||
}
|
@ -0,0 +1,228 @@
|
||||
{
|
||||
"version": "1.22.0",
|
||||
"createdWith": "Open Stage Control",
|
||||
"type": "fragment",
|
||||
"content": {
|
||||
"type": "panel",
|
||||
"top": 0,
|
||||
"left": 0,
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_val",
|
||||
"visible": true,
|
||||
"interaction": true,
|
||||
"comments": "",
|
||||
"width": 130,
|
||||
"height": 340,
|
||||
"expand": true,
|
||||
"colorText": "auto",
|
||||
"colorWidget": "auto",
|
||||
"colorStroke": "auto",
|
||||
"colorFill": "auto",
|
||||
"alphaStroke": "auto",
|
||||
"alphaFillOff": "auto",
|
||||
"alphaFillOn": "auto",
|
||||
"lineWidth": "auto",
|
||||
"borderRadius": "auto",
|
||||
"padding": "auto",
|
||||
"html": "",
|
||||
"css": "",
|
||||
"colorBg": "auto",
|
||||
"layout": "default",
|
||||
"justify": "start",
|
||||
"gridTemplate": "",
|
||||
"contain": true,
|
||||
"scroll": true,
|
||||
"innerPadding": true,
|
||||
"verticalTabs": false,
|
||||
"variables": "@{parent.variables}",
|
||||
"traversing": false,
|
||||
"value": "@{this.id}_rslider",
|
||||
"default": "",
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"typeTags": "",
|
||||
"decimals": 2,
|
||||
"target": "",
|
||||
"ignoreDefaults": false,
|
||||
"bypass": true,
|
||||
"onCreate": "",
|
||||
"onValue": "",
|
||||
"widgets": [
|
||||
{
|
||||
"type": "input",
|
||||
"top": "auto",
|
||||
"left": 0,
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_input_min",
|
||||
"visible": true,
|
||||
"interaction": true,
|
||||
"comments": "",
|
||||
"width": "100%",
|
||||
"height": 30,
|
||||
"expand": "false",
|
||||
"colorText": "auto",
|
||||
"colorWidget": "auto",
|
||||
"colorStroke": "auto",
|
||||
"colorFill": "auto",
|
||||
"alphaStroke": "auto",
|
||||
"alphaFillOff": "auto",
|
||||
"alphaFillOn": "auto",
|
||||
"lineWidth": "auto",
|
||||
"borderRadius": "auto",
|
||||
"padding": "auto",
|
||||
"html": "",
|
||||
"css": ":host {\n\n top: calc(100% - 30rem);\n\n}",
|
||||
"align": "center",
|
||||
"unit": "",
|
||||
"asYouType": false,
|
||||
"numeric": true,
|
||||
"validation": "",
|
||||
"maxLength": "",
|
||||
"value": "@{@{parent.id}_rslider.value.0}",
|
||||
"default": "@{parent.variables.min}",
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"typeTags": "",
|
||||
"decimals": "@{parent.variables.decimals}",
|
||||
"target": "",
|
||||
"ignoreDefaults": false,
|
||||
"bypass": true,
|
||||
"onCreate": "",
|
||||
"onValue": ""
|
||||
},
|
||||
{
|
||||
"type": "range",
|
||||
"top": 60,
|
||||
"left": 0,
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_rslider",
|
||||
"visible": true,
|
||||
"interaction": true,
|
||||
"comments": "",
|
||||
"width": "100%",
|
||||
"height": "auto",
|
||||
"expand": false,
|
||||
"colorText": "auto",
|
||||
"colorWidget": "auto",
|
||||
"colorStroke": "auto",
|
||||
"colorFill": "auto",
|
||||
"alphaStroke": "auto",
|
||||
"alphaFillOff": "auto",
|
||||
"alphaFillOn": "auto",
|
||||
"lineWidth": "auto",
|
||||
"borderRadius": "auto",
|
||||
"padding": "auto",
|
||||
"html": "",
|
||||
"css": ":host {\n\n height: calc(100% - 90rem);\n\n}",
|
||||
"design": "default",
|
||||
"knobSize": "auto",
|
||||
"horizontal": false,
|
||||
"pips": false,
|
||||
"dashed": false,
|
||||
"gradient": [],
|
||||
"snap": true,
|
||||
"spring": false,
|
||||
"doubleTap": false,
|
||||
"range": "{\n \"min\": @{parent.variables.min},\n \"max\": @{parent.variables.max}\n}",
|
||||
"logScale": false,
|
||||
"sensitivity": 1,
|
||||
"steps": "",
|
||||
"value": "[@{@{parent.id}_input_min.value}, @{@{parent.id}_input_max.value}]",
|
||||
"default": "[\n @{parent.variables.min},\n @{parent.variables.max}\n]",
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"typeTags": "i",
|
||||
"decimals": 2,
|
||||
"target": "",
|
||||
"ignoreDefaults": false,
|
||||
"bypass": false,
|
||||
"onCreate": "",
|
||||
"onValue": "var parentVariables = getProp('parent', 'variables')\nif (parentVariables.grandparent) {\n set(parentVariables.grandparent + '_vals', value)\n}",
|
||||
"onTouch": ""
|
||||
},
|
||||
{
|
||||
"type": "input",
|
||||
"width": "100%",
|
||||
"height": 30,
|
||||
"left": 0,
|
||||
"top": 30,
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_input_max",
|
||||
"visible": true,
|
||||
"interaction": true,
|
||||
"comments": "",
|
||||
"expand": "false",
|
||||
"css": "",
|
||||
"address": "auto",
|
||||
"colorText": "auto",
|
||||
"colorWidget": "auto",
|
||||
"colorStroke": "auto",
|
||||
"colorFill": "auto",
|
||||
"alphaStroke": "auto",
|
||||
"alphaFillOff": "auto",
|
||||
"alphaFillOn": "auto",
|
||||
"lineWidth": "auto",
|
||||
"borderRadius": "auto",
|
||||
"padding": "auto",
|
||||
"html": "",
|
||||
"align": "center",
|
||||
"unit": "",
|
||||
"asYouType": false,
|
||||
"numeric": true,
|
||||
"validation": "",
|
||||
"maxLength": "",
|
||||
"value": "@{@{parent.id}_rslider.value.1}",
|
||||
"default": "@{parent.variables.max}",
|
||||
"linkId": "",
|
||||
"preArgs": "",
|
||||
"typeTags": "",
|
||||
"decimals": "@{parent.variables.decimals}",
|
||||
"target": "",
|
||||
"ignoreDefaults": false,
|
||||
"bypass": true,
|
||||
"onCreate": "",
|
||||
"onValue": ""
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"top": 0,
|
||||
"left": 0,
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_rslider_label",
|
||||
"visible": true,
|
||||
"comments": "",
|
||||
"width": "100%",
|
||||
"height": 30,
|
||||
"expand": "false",
|
||||
"colorText": "auto",
|
||||
"colorWidget": "auto",
|
||||
"colorStroke": "auto",
|
||||
"colorFill": "auto",
|
||||
"alphaStroke": "auto",
|
||||
"alphaFillOff": "auto",
|
||||
"alphaFillOn": "auto",
|
||||
"lineWidth": "auto",
|
||||
"borderRadius": "auto",
|
||||
"padding": "auto",
|
||||
"html": "",
|
||||
"css": "",
|
||||
"vertical": false,
|
||||
"wrap": false,
|
||||
"align": "center",
|
||||
"value": "@{parent.variables.rslider_label}",
|
||||
"default": "",
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"decimals": 2,
|
||||
"target": "",
|
||||
"onCreate": "",
|
||||
"onValue": ""
|
||||
}
|
||||
],
|
||||
"tabs": []
|
||||
}
|
||||
}
|
@ -0,0 +1,186 @@
|
||||
{
|
||||
"version": "1.22.0",
|
||||
"createdWith": "Open Stage Control",
|
||||
"type": "fragment",
|
||||
"content": {
|
||||
"type": "panel",
|
||||
"top": 0,
|
||||
"left": 0,
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_val",
|
||||
"visible": true,
|
||||
"interaction": true,
|
||||
"comments": "",
|
||||
"width": "100%",
|
||||
"height": "100%",
|
||||
"expand": "false",
|
||||
"colorText": "auto",
|
||||
"colorWidget": "auto",
|
||||
"colorStroke": "auto",
|
||||
"colorFill": "auto",
|
||||
"alphaStroke": "auto",
|
||||
"alphaFillOff": "auto",
|
||||
"alphaFillOn": "auto",
|
||||
"lineWidth": "auto",
|
||||
"borderRadius": "auto",
|
||||
"padding": "auto",
|
||||
"html": "",
|
||||
"css": ":host {\n\n left: calc(100% - 80rem);\n\n}",
|
||||
"colorBg": "auto",
|
||||
"layout": "default",
|
||||
"justify": "start",
|
||||
"gridTemplate": "",
|
||||
"contain": true,
|
||||
"scroll": true,
|
||||
"innerPadding": true,
|
||||
"verticalTabs": false,
|
||||
"variables": "@{parent.variables}",
|
||||
"traversing": false,
|
||||
"value": "",
|
||||
"default": "",
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"typeTags": "",
|
||||
"decimals": 2,
|
||||
"target": "",
|
||||
"ignoreDefaults": false,
|
||||
"bypass": false,
|
||||
"onCreate": "",
|
||||
"onValue": "",
|
||||
"widgets": [
|
||||
{
|
||||
"type": "fader",
|
||||
"top": 30,
|
||||
"left": 0,
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_slider",
|
||||
"visible": true,
|
||||
"comments": "",
|
||||
"width": "100%",
|
||||
"height": "auto",
|
||||
"expand": "false",
|
||||
"colorText": "auto",
|
||||
"colorWidget": "auto",
|
||||
"colorStroke": "auto",
|
||||
"colorFill": "auto",
|
||||
"alphaStroke": "auto",
|
||||
"alphaFillOff": "auto",
|
||||
"alphaFillOn": "auto",
|
||||
"lineWidth": "auto",
|
||||
"borderRadius": "auto",
|
||||
"padding": "auto",
|
||||
"html": "",
|
||||
"css": ":host {\n\n height: calc(100% - 60rem);\n\n}",
|
||||
"value": "@{@{parent.id}_input.value}",
|
||||
"default": 0.75,
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"decimals": 2,
|
||||
"target": "",
|
||||
"onCreate": "",
|
||||
"onValue": "var parentVariables = getProp('parent', 'variables')\nif (parentVariables.grandparent) {\n set(parentVariables.grandparent + '_vals', value)\n}",
|
||||
"interaction": true,
|
||||
"typeTags": "",
|
||||
"ignoreDefaults": false,
|
||||
"bypass": false,
|
||||
"design": "default",
|
||||
"knobSize": "auto",
|
||||
"horizontal": false,
|
||||
"pips": false,
|
||||
"dashed": false,
|
||||
"gradient": [],
|
||||
"snap": true,
|
||||
"spring": false,
|
||||
"doubleTap": false,
|
||||
"range": "{\n \"min\": @{parent.variables.min},\n \"max\": @{parent.variables.max}\n}",
|
||||
"logScale": false,
|
||||
"sensitivity": 1,
|
||||
"steps": "",
|
||||
"onTouch": "",
|
||||
"origin": "auto"
|
||||
},
|
||||
{
|
||||
"type": "input",
|
||||
"top": "auto",
|
||||
"left": 0,
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_input",
|
||||
"visible": true,
|
||||
"comments": "",
|
||||
"width": "100%",
|
||||
"height": 30,
|
||||
"expand": "false",
|
||||
"colorText": "auto",
|
||||
"colorWidget": "auto",
|
||||
"colorStroke": "auto",
|
||||
"colorFill": "auto",
|
||||
"alphaStroke": "auto",
|
||||
"alphaFillOff": "auto",
|
||||
"alphaFillOn": "auto",
|
||||
"lineWidth": "auto",
|
||||
"borderRadius": "auto",
|
||||
"padding": "auto",
|
||||
"html": "",
|
||||
"css": ":host {\n\n top: calc(100% - 30rem);\n\n}",
|
||||
"align": "center",
|
||||
"value": "@{@{parent.id}_slider.value}",
|
||||
"default": 0.75,
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"decimals": 2,
|
||||
"target": "",
|
||||
"onCreate": "",
|
||||
"onValue": "",
|
||||
"interaction": true,
|
||||
"unit": "",
|
||||
"asYouType": false,
|
||||
"numeric": false,
|
||||
"validation": "",
|
||||
"maxLength": "",
|
||||
"typeTags": "",
|
||||
"ignoreDefaults": false,
|
||||
"bypass": true
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"top": 0,
|
||||
"left": 0,
|
||||
"lock": false,
|
||||
"id": "@{parent.id}_slider_label",
|
||||
"visible": true,
|
||||
"comments": "",
|
||||
"width": "100%",
|
||||
"height": 30,
|
||||
"expand": "false",
|
||||
"colorText": "auto",
|
||||
"colorWidget": "auto",
|
||||
"colorStroke": "auto",
|
||||
"colorFill": "auto",
|
||||
"alphaStroke": "auto",
|
||||
"alphaFillOff": "auto",
|
||||
"alphaFillOn": "auto",
|
||||
"lineWidth": "auto",
|
||||
"borderRadius": "auto",
|
||||
"padding": "auto",
|
||||
"html": "",
|
||||
"css": "",
|
||||
"vertical": false,
|
||||
"wrap": false,
|
||||
"align": "center",
|
||||
"value": "@{parent.variables.slider_label}",
|
||||
"default": "",
|
||||
"linkId": "",
|
||||
"address": "auto",
|
||||
"preArgs": "",
|
||||
"decimals": 2,
|
||||
"target": "",
|
||||
"onCreate": "",
|
||||
"onValue": ""
|
||||
}
|
||||
],
|
||||
"tabs": []
|
||||
}
|
||||
}
|
@ -0,0 +1,277 @@
|
||||
const {resolve} = nativeRequire("path");
|
||||
var fs = nativeRequire("fs");
|
||||
|
||||
stringifyToDepth = function(data, maxDepth){
|
||||
var prettyString = ""
|
||||
var rCount = 0
|
||||
var writeArray
|
||||
var indent;
|
||||
|
||||
if(maxDepth === 0) {
|
||||
JSON.stringify(data)
|
||||
} else {
|
||||
indent = function(size) {return Array.from({length: size}, () => " ").join("")}
|
||||
writeArray = function(array) {
|
||||
prettyString = prettyString + indent(rCount) + "[\n"
|
||||
rCount = rCount + 1
|
||||
if(rCount < maxDepth) {
|
||||
array.forEach(item => writeArray(item))
|
||||
} else {
|
||||
var formmattedArray;
|
||||
formattedArray = array.map(item => indent(rCount) + JSON.stringify(item)).join(",\n")
|
||||
formattedArray = formattedArray.replaceAll("[", "[ ").replaceAll("]", " ]").replaceAll(",", ", ")
|
||||
prettyString = prettyString + formattedArray
|
||||
}
|
||||
rCount = rCount - 1;
|
||||
prettyString = prettyString + "\n" + indent(rCount) + "],\n";
|
||||
}
|
||||
|
||||
writeArray(data)
|
||||
prettyString = prettyString.replaceAll(",\n\n", "\n").slice(0, -2);
|
||||
return prettyString
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
init: function(){
|
||||
// this will be executed once when the osc server starts
|
||||
},
|
||||
|
||||
oscInFilter:function(data) {
|
||||
|
||||
var {host, port, address, args} = data
|
||||
|
||||
//console.log(data)
|
||||
|
||||
if (address === '/playing') {
|
||||
|
||||
var modelPath = resolve(args[0].value)
|
||||
var model = loadJSON(modelPath)
|
||||
//receive('/STATE/OPEN', guiStatePath)
|
||||
|
||||
receive("/ref_uid", model.ref_uid)
|
||||
|
||||
receive("/order_seed", model.order_seed)
|
||||
receive("/dur_seed", model.dur_seed)
|
||||
receive("/weights_seed", model.motifs_seed)
|
||||
|
||||
|
||||
var envValsFlat = model.entrances_probs_vals.slice(5)
|
||||
var envSize = envValsFlat.length / 2
|
||||
var envVals = new Array(64).fill({type: 'f', value: 0})
|
||||
for (var i = 0; i < envSize; i++) {
|
||||
envVals[i] = [envValsFlat[i * 2], envValsFlat[i * 2 + 1]]
|
||||
}
|
||||
receive("/entrances_probs_dur_env_size", envSize)
|
||||
receive("/entrances_probs_chord_val_slider", model.entrances_probs_vals[0])
|
||||
receive("/entrances_probs_pad_val_rslider", model.entrances_probs_vals.slice(1, 3))
|
||||
receive("/entrances_probs_dur_env_rslider", ...model.entrances_probs_vals.slice(3, 5))
|
||||
receive("/entrances_probs_dur_env_canvas", ...envVals)
|
||||
|
||||
var envValsFlat = model.passages_probs_vals.slice(5)
|
||||
var envSize = envValsFlat.length / 2
|
||||
var envVals = new Array(64).fill({type: 'f', value: 0})
|
||||
for (var i = 0; i < envSize; i++) {
|
||||
envVals[i] = [envValsFlat[i * 2], envValsFlat[i * 2 + 1]]
|
||||
}
|
||||
receive("/passages_probs_dur_env_size", envSize)
|
||||
receive("/passages_probs_chord_val_slider", model.passages_probs_vals[0])
|
||||
receive("/passages_probs_pad_val_rslider", model.passages_probs_vals.slice(1, 3))
|
||||
receive("/passages_probs_dur_env_rslider", ...model.passages_probs_vals.slice(3, 5))
|
||||
receive("/passages_probs_dur_env_canvas", ...envVals)
|
||||
|
||||
var envValsFlat = model.exits_probs_vals.slice(5)
|
||||
var envSize = envValsFlat.length / 2
|
||||
var envVals = new Array(64).fill({type: 'f', value: 0})
|
||||
for (var i = 0; i < envSize; i++) {
|
||||
envVals[i] = [envValsFlat[i * 2], envValsFlat[i * 2 + 1]]
|
||||
}
|
||||
receive("/exits_probs_dur_env_size", envSize)
|
||||
receive("/exits_probs_chord_val_slider", model.exits_probs_vals[0])
|
||||
receive("/exits_probs_pad_val_rslider", model.exits_probs_vals.slice(1, 3))
|
||||
receive("/exits_probs_dur_env_rslider", ...model.exits_probs_vals.slice(3, 5))
|
||||
receive("/exits_probs_dur_env_canvas", ...envVals)
|
||||
|
||||
// no idea why I need to call the range sliders twice
|
||||
receive("/range_matrix/0_val_rslider", ...model.ranges[0])
|
||||
receive("/range_matrix/1_val_rslider", ...model.ranges[1])
|
||||
receive("/range_matrix/2_val_rslider", ...model.ranges[2])
|
||||
receive("/range_matrix/3_val_rslider", ...model.ranges[3])
|
||||
|
||||
receive("/passages_weights/0_val_slider", model.passages_weights[0])
|
||||
receive("/passages_weights/1_val_slider", model.passages_weights[1])
|
||||
receive("/passages_weights/2_val_slider", model.passages_weights[2])
|
||||
receive("/passages_weights/3_val_slider", model.passages_weights[3])
|
||||
receive("/passages_weights/4_val_slider", model.passages_weights[4])
|
||||
|
||||
receive("/order", stringifyToDepth(model.order, 1))
|
||||
|
||||
receive("/sus_weights/0_val_slider", model.sus_weights[0])
|
||||
receive("/sus_weights/1_val_slider", model.sus_weights[1])
|
||||
receive("/sus_weights/2_val_slider", model.sus_weights[2])
|
||||
|
||||
receive("/order_size_rslider", ...model.order_size)
|
||||
receive("/passages_size_rslider", ...model.passages_size)
|
||||
|
||||
receive("/mus_seq", stringifyToDepth(model.music_data, 3))
|
||||
receive("/cur_play_index", args[1].value)
|
||||
}
|
||||
|
||||
if (address === '/generated') {
|
||||
|
||||
//var guiStatePath = resolve(__dirname + "/../../resources/tmp/tmp_gui_state.json")
|
||||
//var musPath = resolve(__dirname + "/../../resources/tmp/tmp_music.json")
|
||||
var ledgerPath = resolve(__dirname + "/../../resources/piece_ledger.json")
|
||||
//var guiState = loadJSON(guiStatePath)
|
||||
//var musState = loadJSON(musPath)
|
||||
//guiState.mus_seq = musState.music_data
|
||||
//saveJSON(guiStatePath, guiState)
|
||||
var ledger = loadJSON(ledgerPath).ledger
|
||||
ledger.push("tmp")
|
||||
var model = JSON.parse(args[1].value);
|
||||
receive("/ledger", JSON.stringify(ledger, null, ' ').replace(/['"]+/g, ''))
|
||||
receive("/mus_seq", stringifyToDepth(model.music_data, 3))
|
||||
receive("/order", stringifyToDepth(model.order, 1))
|
||||
}
|
||||
|
||||
if (address === '/committed') {
|
||||
try {
|
||||
/*
|
||||
var guiStatePath = resolve(__dirname + "/../../resources/tmp/tmp_gui_state.json")
|
||||
var curUID = args[0].value
|
||||
var state = loadJSON(guiStatePath)
|
||||
state.cur_uid = curUID
|
||||
var dir = resolve(__dirname + "/../../resources/" + curUID)
|
||||
if (!fs.existsSync(dir)){
|
||||
fs.mkdirSync(dir);
|
||||
}
|
||||
guiStatePath = resolve(__dirname + "/../../resources/" + curUID + "/" + curUID + "_gui_state.json")
|
||||
saveJSON(guiStatePath, state)
|
||||
*/
|
||||
} catch (e) {
|
||||
console.log(`error while committing`)
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
var ledgerPath = args[1].value
|
||||
receive("/ledger", JSON.stringify(loadJSON(ledgerPath).ledger, null, ' ').replace(/['"]+/g, ''))
|
||||
return
|
||||
}
|
||||
|
||||
if (address === '/load_state') {
|
||||
/*
|
||||
var ref_uid = args[0].value
|
||||
loadState(loadJSON("../../resources/" + ref_uid + "/" + ref_uid + "_gui_state.json"))
|
||||
receive('/commit')
|
||||
*/
|
||||
return
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
},
|
||||
|
||||
oscOutFilter:function(data) {
|
||||
|
||||
var {host, port, address, args} = data
|
||||
|
||||
//console.log(data)
|
||||
|
||||
if (address === '/generate') {
|
||||
try {
|
||||
var state = JSON.parse(args[0].value)
|
||||
|
||||
//console.log(__dirname)
|
||||
var modelPath = resolve(__dirname + "/../../resources/tmp/tmp_mus_model.json")
|
||||
var model = {}
|
||||
model.schema_version = "1.0"
|
||||
model.cur_uid = "tmp"
|
||||
model.ref_uid = state.ref_uid
|
||||
if(model.ref_uid == "nil" || model.ref_uid == "" || model.ref_uid == "[" || model.ref_uid == "[]") {delete model["ref_uid"]}
|
||||
model.order_seed = state.order_seed
|
||||
model.dur_seed = state.dur_seed
|
||||
model.motifs_seed = state.weights_seed
|
||||
model.entrances_probs_vals = state.entrances_probs_vals
|
||||
model.passages_probs_vals = state.passages_probs_vals
|
||||
model.exits_probs_vals = state.exits_probs_vals
|
||||
model.ranges = [
|
||||
state["range_matrix/0_val_rslider"],
|
||||
state["range_matrix/1_val_rslider"],
|
||||
state["range_matrix/2_val_rslider"],
|
||||
state["range_matrix/3_val_rslider"]
|
||||
]
|
||||
model.passages_weights = [
|
||||
state["passages_weights/0_val_slider"],
|
||||
state["passages_weights/1_val_slider"],
|
||||
state["passages_weights/2_val_slider"],
|
||||
state["passages_weights/3_val_slider"],
|
||||
state["passages_weights/4_val_slider"]
|
||||
]
|
||||
if(state.order_lock == 1){
|
||||
model.order = JSON.parse(state.order)
|
||||
}
|
||||
model.sus_weights = [
|
||||
state["sus_weights/0_val_slider"],
|
||||
state["sus_weights/1_val_slider"],
|
||||
state["sus_weights/2_val_slider"]
|
||||
]
|
||||
model.order_size = state.order_size_rslider
|
||||
model.passages_size = state.passages_size_rslider
|
||||
|
||||
model.motif_edited = false
|
||||
model.order_edited = false
|
||||
//console.log(model)
|
||||
saveJSON(modelPath, model)
|
||||
|
||||
/*
|
||||
var ledgerPanelState = JSON.parse(args[1].value)
|
||||
delete ledgerPanelState.ref_uid
|
||||
var omitKeys = Object.keys(ledgerPanelState).concat(["generate", "commit"])
|
||||
//console.log(omitKeys[0])
|
||||
for(k in omitKeys) {
|
||||
//console.log(omitKeys[k])
|
||||
delete state[omitKeys[k]]
|
||||
}
|
||||
var guiStatePath = resolve(__dirname + "/../../resources/tmp/tmp_gui_state.json.json")
|
||||
saveJSON(guiStatePath, state)
|
||||
*/
|
||||
|
||||
args = args.slice(0, 1)
|
||||
args[0].value = modelPath
|
||||
return {host, port, address, args}
|
||||
} catch (e) {
|
||||
//console.log(`error while building model ${args[0].value}`)
|
||||
console.log(`error while building model`)
|
||||
console.error(e)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (address === '/load_ledger') {
|
||||
//console.log(loadJSON(args[0].value))
|
||||
receive('/ledger', JSON.stringify(loadJSON(args[0].value).ledger, null, ' ').replace(/['"]+/g, ''))
|
||||
return data
|
||||
}
|
||||
|
||||
if (address === '/commit') {
|
||||
var model = {}
|
||||
model.music = JSON.parse(args[0].value)
|
||||
args[0].value = JSON.stringify(model)
|
||||
return {host, port, address, args}
|
||||
}
|
||||
|
||||
if ([/*'/commit', */'/save_ledger', '/transport'].includes(address)) {
|
||||
//console.log(data)
|
||||
return data
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
},
|
||||
|
||||
unload: function(){
|
||||
// this will be executed when the custom module is reloaded
|
||||
},
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,581 @@
|
||||
(
|
||||
// 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;
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -0,0 +1,75 @@
|
||||
{
|
||||
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 ] ], 1.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 ] ]
|
||||
],
|
||||
seed: 314491,
|
||||
ref_seed: nil
|
||||
}
|
@ -0,0 +1,719 @@
|
||||
(
|
||||
// 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");
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,57 @@
|
||||
{
|
||||
"music_data":
|
||||
[
|
||||
[
|
||||
[
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ] ], 0 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ "Rest" ], [ 2, 0, 0, -1, 0, 0 ] ], 1.625 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 2, 0, 0, -2, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 0.875 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 0.625 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.625 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 1, 0, -1, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.25 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 2, 0, 0, -1, -1, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.375 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 1, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 2, -1, 0, 0, 0, -1 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.125 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 2, -2, 0, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.5 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.375 ]
|
||||
],
|
||||
[
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 0.5 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 2 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 0.625 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 0.875 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ "Rest" ], [ 2, 0, 0, -1, 0, 0 ] ], 0 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 2, 0, 0, -1, 0, 0 ] ], 0 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0 ],
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0.75 ]
|
||||
]
|
||||
]
|
||||
],
|
||||
"last_changes":
|
||||
[
|
||||
[ [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ],
|
||||
[ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ],
|
||||
[ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ],
|
||||
[ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ],
|
||||
[ [ 0, 0, 0, 0, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ]
|
||||
],
|
||||
"cur_uid": "46b6952a",
|
||||
"ref_uid": "7e170ef8",
|
||||
"order_seed": 969134,
|
||||
"dur_seed": 384656,
|
||||
"motifs_seed": 435714,
|
||||
"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, 1, 3 ], [ 2, 2, 2, 2, 2, 2, 2, 2, 2 ], [ ] ],
|
||||
[ [ 0, 2, 3 ], [ 1, 1, 1, 1 ], [ ] ]
|
||||
],
|
||||
"sus_weights": [ 0.75, 0.69, 0.75 ],
|
||||
"order_size": [ 2, 6 ],
|
||||
"passages_size": [ 0, 10 ]
|
||||
}
|
@ -0,0 +1,718 @@
|
||||
(
|
||||
// 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");
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,85 @@
|
||||
{
|
||||
"music_data":
|
||||
[
|
||||
[
|
||||
[
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1.75 ],
|
||||
[ [ [ "Rest" ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0 ],
|
||||
[ [ [ "Rest" ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 0 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 1.25 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 1.75 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ -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 ], [ -1, 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, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 0.875 ],
|
||||
[ [ [ 1, 0, 0, -1, 0, 0 ], [ -1, 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, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 1.625 ],
|
||||
[ [ [ 1, -1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 1.75 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0.875 ]
|
||||
],
|
||||
[
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ -1, 1, 1, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0.625 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, -1 ], [ 1, 0, 0, -1, 0, 0 ] ], 1.625 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 1.125 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 1 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0.5 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 1 ], [ 1, 0, 0, -1, 0, 0 ] ], 1.625 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 1.5 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, -1 ], [ 1, 0, 0, -1, 0, 0 ] ], 0.5 ]
|
||||
],
|
||||
[
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 0, 1, 0, 0, 0, -1 ], [ 1, 0, 0, -1, 0, 0 ] ], 0.5 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 0, 1, 0, 0, 0, -1 ], [ 1, 0, 0, -1, 0, 0 ] ], 1.5 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 1, 0, -1 ], [ 0, 1, 0, 0, 0, -1 ], [ 1, 0, 0, -1, 0, 0 ] ], 1.5 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 0, 1, 0, 0, 0, -1 ], [ 1, 0, 0, -1, 0, 0 ] ], 1.125 ]
|
||||
],
|
||||
[
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 0, 1, 0, 0, 0, -1 ], [ "Rest" ] ], 0 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 1, 0, 0, 0, -1 ], [ "Rest" ] ], 0 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1.375 ]
|
||||
],
|
||||
[
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 1.75 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 1.875 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0.75 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 1.25 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 1 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 1.375 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 2 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, 0, -1, -1, 0 ], [ "Rest" ], [ 1, 0, 0, -1, 0, 0 ] ], 1.75 ],
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 1, 0, 0, -1, 0, 0 ] ], 0 ],
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1 ]
|
||||
]
|
||||
]
|
||||
],
|
||||
"last_changes":
|
||||
[
|
||||
[ [ 0, 1, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ],
|
||||
[ [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ],
|
||||
[ [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ],
|
||||
[ [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ],
|
||||
[ [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ]
|
||||
],
|
||||
"cur_uid": "4c01589b",
|
||||
"ref_uid": "nil",
|
||||
"order_seed": 720097,
|
||||
"dur_seed": 979064,
|
||||
"motifs_seed": 718021,
|
||||
"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 ], [ 1, 3, 0, 1, 1, 3, 0, 0, 3, 0, 0, 3 ], [ ] ],
|
||||
[ [ 1, 0, 3 ], [ 2, 2, 2, 2, 2, 2, 2, 2 ], [ ] ],
|
||||
[ [ 3, 2, 0 ], [ 1, 1, 1, 1 ], [ ] ],
|
||||
[ [ 0 ], [ 2 ], [ 3, 1 ] ],
|
||||
[ [ 0, 2, 3 ], [ 1, 1, 1, 1, 1, 1 ], [ ] ]
|
||||
],
|
||||
"sus_weights": [ 0.75, 0.69, 0.75 ],
|
||||
"order_size": [ 2, 6 ],
|
||||
"passages_size": [ 0, 10 ]
|
||||
}
|
@ -0,0 +1,757 @@
|
||||
(
|
||||
// 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 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;
|
||||
|
||||
|
||||
// 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, 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",
|
||||
"motif_edited", "order_edited"
|
||||
];
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
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",
|
||||
"motif_edited", "order_edited"
|
||||
];
|
||||
|
||||
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,
|
||||
motifEdited, orderEdited = 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[..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;
|
||||
|
||||
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));
|
||||
//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");
|
@ -0,0 +1,105 @@
|
||||
{
|
||||
"music_data":
|
||||
[
|
||||
[
|
||||
[
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 3.75 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1.125 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ] ], 1.375 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 1.75 ],
|
||||
[ [ [ "Rest" ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ] ], 0.875 ],
|
||||
[ [ [ "Rest" ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 1 ] ], 1 ],
|
||||
[ [ [ "Rest" ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 1 ] ], 0 ],
|
||||
[ [ [ "Rest" ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ] ], 1.75 ],
|
||||
[ [ [ "Rest" ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ] ], 1.625 ],
|
||||
[ [ [ "Rest" ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 2 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 0.875 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 5 ]
|
||||
],
|
||||
[
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 1.375 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, -1, 0, 1 ], [ 0, 0, 0, -1, 0, 0 ] ], 0.875 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, -1, 1, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 1.875 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 1.875 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 1.25 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 1, -1, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 0.875 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 1 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 1 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, 0, -1, 0, -1 ], [ 0, 0, 0, -1, 0, 0 ] ], 2 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 3.625 ]
|
||||
],
|
||||
[
|
||||
[ [ [ 0, 0, 0, -1, 0, 1 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 0 ],
|
||||
[ [ [ 0, 0, 0, -1, 0, 1 ], [ 0, -1, 0, 0, 0, 1 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 1 ],
|
||||
[ [ [ 1, -1, 0, -1, 0, 0 ], [ 0, -1, 0, 0, 0, 1 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 0.875 ],
|
||||
[ [ [ 1, -1, 0, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 1.75 ],
|
||||
[ [ [ 1, -1, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 1.5 ],
|
||||
[ [ [ 1, -1, 0, 0, 0, -1 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 0 ],
|
||||
[ [ [ 1, -1, 0, 0, 0, -1 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 1.25 ],
|
||||
[ [ [ 0, 1, 0, -1, 0, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 5.25 ]
|
||||
],
|
||||
[
|
||||
[ [ [ 0, -1, 0, 1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 0, 0, 0, -1, 0, 0 ] ], 1.125 ],
|
||||
[ [ [ 0, -1, 0, 1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, -1, 0, 0, 0, 0 ], [ 1, -1, 0, -1, -1, 0 ] ], 1.125 ],
|
||||
[ [ [ 0, -1, 0, 1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, -1, 1, 0, -1, 0 ], [ 1, -1, 0, -1, -1, 0 ] ], 1.875 ],
|
||||
[ [ [ 0, -1, 0, 1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -2, 0, 0, -1, 0 ], [ 1, -1, 0, -1, -1, 0 ] ], 1.25 ],
|
||||
[ [ [ 0, -1, 0, 1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -2, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, -1 ] ], 1.625 ],
|
||||
[ [ [ 0, -1, 0, 1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, -1 ] ], 0 ],
|
||||
[ [ [ 0, -1, 0, 1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, -1, 1, 0, -1, 0 ] ], 1.5 ],
|
||||
[ [ [ 0, -1, 0, 0, -1, 1 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, -1, 1, 0, -1, 0 ] ], 0.625 ],
|
||||
[ [ [ 0, -1, 0, 0, -1, 1 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -2, 0, 0, -1, 0 ] ], 1.625 ],
|
||||
[ [ [ 1, -1, -1, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -2, 0, 0, -1, 0 ] ], 1.625 ],
|
||||
[ [ [ 1, -1, -1, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -2, 0 ] ], 1.875 ],
|
||||
[ [ [ 1, -1, -1, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 0 ], [ 0, -1, 0, 0, 0, 0 ] ], 5.125 ]
|
||||
],
|
||||
[
|
||||
[ [ [ 1, -1, -1, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -2, 0 ], [ 0, -1, 0, 0, 0, 0 ] ], 0.75 ],
|
||||
[ [ [ 1, -1, -1, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -2, 0 ], [ 0, 0, 0, 0, -1, 0 ] ], 0 ],
|
||||
[ [ [ 0, -1, 0, 1, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -2, 0 ], [ 0, 0, 0, 0, -1, 0 ] ], 0.625 ],
|
||||
[ [ [ 0, -1, 0, 0, -1, 1 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -2, 0 ], [ 0, 0, 0, 0, -1, 0 ] ], 1.375 ],
|
||||
[ [ [ 0, -1, 0, 0, -1, 1 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -2, 0 ], [ 1, -1, -1, 0, -1, 0 ] ], 4.875 ]
|
||||
],
|
||||
[
|
||||
[ [ [ 0, -1, 0, 0, -1, 1 ], [ 1, -1, 0, 0, -1, 0 ], [ "Rest" ], [ 1, -1, -1, 0, -1, 0 ] ], 0.875 ],
|
||||
[ [ [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ "Rest" ], [ 1, -1, -1, 0, -1, 0 ] ], 1.75 ],
|
||||
[ [ [ 0, -1, -1, 0, -1, 1 ], [ 1, -1, 0, 0, -1, 0 ], [ "Rest" ], [ 1, -1, -1, 0, -1, 0 ] ], 1.375 ],
|
||||
[ [ [ 0, -1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ "Rest" ], [ 1, -1, -1, 0, -1, 0 ] ], 4.375 ],
|
||||
[ [ [ "Rest" ], [ 1, -1, 0, 0, -1, 0 ], [ "Rest" ], [ 1, -1, -1, 0, -1, 0 ] ], 0 ],
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 1, -1, -1, 0, -1, 0 ] ], 1.875 ],
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 5 ]
|
||||
]
|
||||
]
|
||||
],
|
||||
"last_changes":
|
||||
[
|
||||
[ [ 0, -1, 0, 0, -1, 1 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -2, 0 ], [ 0, 0, 0, 0, -1, 0 ] ],
|
||||
[ [ 0, -1, 0, 0, -1, 1 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -2, 0 ], [ 1, -1, -1, 0, -1, 0 ] ],
|
||||
[ [ 0, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -2, 0 ], [ 1, -1, -1, 0, -1, 0 ] ],
|
||||
[ [ 0, -1, -1, 0, -1, 1 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -2, 0 ], [ 1, -1, -1, 0, -1, 0 ] ],
|
||||
[ [ 0, -1, 0, 0, 0, 0 ], [ 1, -1, 0, 0, -1, 0 ], [ 1, -1, 0, 0, -2, 0 ], [ 1, -1, -1, 0, -1, 0 ] ]
|
||||
],
|
||||
"cur_uid": "55930f4d",
|
||||
"ref_uid": "nil",
|
||||
"order_seed": 751178,
|
||||
"dur_seed": 630355,
|
||||
"motifs_seed": 318398,
|
||||
"entrances_probs_vals": [ 0.33687943262411, 1.91, 4.44, 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.33687943262411, 1.91, 4.44, 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.33687943262411, 1.91, 4.44, 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":
|
||||
[
|
||||
[ [ 2 ], [ 1, 3, 3, 1, 3, 1, 3, 3, 3, 1, 1 ], [ 0 ] ],
|
||||
[ [ 0, 1, 3 ], [ 2, 2, 2, 2, 2, 2, 2, 2, 2 ], [ ] ],
|
||||
[ [ 3, 2 ], [ 0, 1, 0, 1, 1, 0, 1, 0 ], [ ] ],
|
||||
[ [ 1 ], [ 0, 3, 2, 2, 3, 2, 3, 0, 3, 0, 3, 3 ], [ ] ],
|
||||
[ [ 1 ], [ 2, 3, 0, 0, 3 ], [ ] ],
|
||||
[ [ 1, 3 ], [ 0, 0, 0 ], [ 2 ] ]
|
||||
],
|
||||
"sus_weights": [ 0.75, 0.75, 0.75 ],
|
||||
"order_size": [ 1, 10 ],
|
||||
"passages_size": [ 0, 10 ],
|
||||
"motif_edited": "false",
|
||||
"order_edited": "false"
|
||||
}
|
@ -0,0 +1,723 @@
|
||||
(
|
||||
// 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, 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;
|
||||
}, {
|
||||
i.postln;
|
||||
flatOrder.postln;
|
||||
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);
|
||||
};
|
||||
});
|
||||
|
||||
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, 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, {
|
||||
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, 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, dFormat, condition, 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"]);
|
||||
});
|
||||
|
||||
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;
|
||||
|
||||
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 file;
|
||||
file = File((dir +/+ ".." +/+ "resources" +/+ uid +/+ uid ++ "_mus_model" ++ ".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");
|
@ -0,0 +1,41 @@
|
||||
{
|
||||
"music_data":
|
||||
[
|
||||
[
|
||||
[
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1 ],
|
||||
[ [ [ "Rest" ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0 ],
|
||||
[ [ [ 1, -1, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 2.625 ],
|
||||
[ [ [ 1, -1, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 2.875 ],
|
||||
[ [ [ "Rest" ], [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0 ],
|
||||
[ [ [ "Rest" ], [ -1, 0, 0, 0, 0, 1 ], [ "Rest" ], [ "Rest" ] ], 0 ],
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.25 ]
|
||||
]
|
||||
]
|
||||
],
|
||||
"last_changes":
|
||||
[
|
||||
[ [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ],
|
||||
[ [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, -2, -1, 0 ] ],
|
||||
[ [ 0, 1, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, -2, -1, 0 ] ],
|
||||
[ [ 1, -1, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, -2, -1, 0 ] ],
|
||||
[ [ 1, -1, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, -2, -1, 0 ] ]
|
||||
],
|
||||
"cur_uid": "5cf1e9ab",
|
||||
"ref_uid": "640eeed3",
|
||||
"order_seed": 747498,
|
||||
"dur_seed": 968974,
|
||||
"motifs_seed": 709945,
|
||||
"entrances_probs_vals": [ 1, 0.5, 2, 0, 0.5, 0.26424870466321, 0.75675675675676, 0.42746113989637, 0.77364864864865, 0.5, 0.5, 0.58549222797927, 0.72635135135135, 1, 0.5 ],
|
||||
"passages_probs_vals": [ 1, 1.87, 3.7996946564886, 0, 0.5, 0.5, 0.5, 1, 0.5 ],
|
||||
"exits_probs_vals": [ 1, 0.5, 2, 0, 0.5, 0.26424870466321, 0.75675675675676, 0.42746113989637, 0.77364864864865, 0.5, 0.5, 0.58549222797927, 0.72635135135135, 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 ], [ 1, 0, 1 ], [ 3 ] ]
|
||||
],
|
||||
"sus_weights": [ 1, 0, 0 ],
|
||||
"order_size": [ 1, 3 ],
|
||||
"passages_size": [ 0, 2 ]
|
||||
}
|
@ -0,0 +1,716 @@
|
||||
(
|
||||
// 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, {
|
||||
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;
|
||||
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]).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 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, dFormat, condition, 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;
|
||||
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;
|
||||
|
||||
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.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});
|
||||
ledger.postln;
|
||||
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 ++ "_mus_model" ++ ".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");
|
@ -0,0 +1,48 @@
|
||||
{
|
||||
"music_data":
|
||||
[
|
||||
[
|
||||
[
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 2.875 ],
|
||||
[ [ [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1.875 ],
|
||||
[ [ [ 1, 0, 0, 0, -1, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 2.25 ]
|
||||
],
|
||||
[
|
||||
[ [ [ 1, 0, 0, 0, -1, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, -2, -1, 0 ] ], 1.875 ],
|
||||
[ [ [ 1, 0, 0, 0, -1, 0 ], [ "Rest" ], [ 2, 0, 1, -2, -1, 0 ], [ 2, 0, 0, -2, -1, 0 ] ], 3.5 ],
|
||||
[ [ [ 3, 0, -1, -2, -1, 0 ], [ "Rest" ], [ 2, 0, 1, -2, -1, 0 ], [ 2, 0, 0, -2, -1, 0 ] ], 2.375 ],
|
||||
[ [ [ 3, 0, -1, -2, -1, 0 ], [ 2, 0, -1, -2, -1, 0 ], [ 2, 0, 1, -2, -1, 0 ], [ 2, 0, 0, -2, -1, 0 ] ], 2.5 ],
|
||||
[ [ [ 3, 0, -1, -2, -1, 0 ], [ "Rest" ], [ 2, 0, 1, -2, -1, 0 ], [ 2, 0, 0, -2, -1, 0 ] ], 3.625 ],
|
||||
[ [ [ 3, 0, -1, -2, -1, 0 ], [ "Rest" ], [ "Rest" ], [ 2, 0, 0, -2, -1, 0 ] ], 2.75 ],
|
||||
[ [ [ 3, 0, -1, -2, -1, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 3.625 ],
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 2.125 ]
|
||||
]
|
||||
]
|
||||
],
|
||||
"last_changes":
|
||||
[
|
||||
[ [ 1, 0, -1, 0, 0, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, -2, -1, 0 ] ],
|
||||
[ [ 1, 0, 0, 0, -1, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, -2, -1, 0 ] ],
|
||||
[ [ 1, 0, 0, 0, -1, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 2, 0, 1, -2, -1, 0 ], [ 2, 0, 0, -2, -1, 0 ] ],
|
||||
[ [ 3, 0, -1, -2, -1, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 2, 0, 1, -2, -1, 0 ], [ 2, 0, 0, -2, -1, 0 ] ],
|
||||
[ [ 3, 0, -1, -2, -1, 0 ], [ 2, 0, -1, -2, -1, 0 ], [ 2, 0, 1, -2, -1, 0 ], [ 2, 0, 0, -2, -1, 0 ] ]
|
||||
],
|
||||
"cur_uid": "5e947063",
|
||||
"ref_uid": "640eeed3",
|
||||
"order_seed": 190057,
|
||||
"dur_seed": 196835,
|
||||
"motifs_seed": 211273,
|
||||
"entrances_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 ],
|
||||
"passages_probs_vals": [ 0, 1.87, 3.7996946564886, 0, 0.5, 0.5, 0.5, 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 ], [ 0, 0 ], [ 3, 1 ] ],
|
||||
[ [ 3 ], [ 2, 0, 1 ], [ ] ]
|
||||
],
|
||||
"sus_weights": [ 1, 0, 0 ],
|
||||
"order_size": [ 1, 3 ],
|
||||
"passages_size": [ 0, 2 ]
|
||||
}
|
@ -0,0 +1,741 @@
|
||||
(
|
||||
// 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");
|
@ -0,0 +1,56 @@
|
||||
{
|
||||
"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 ]
|
||||
}
|
@ -0,0 +1,735 @@
|
||||
(
|
||||
// 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, {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");
|
@ -0,0 +1,91 @@
|
||||
{
|
||||
"music_data":
|
||||
[
|
||||
[
|
||||
[
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 0.75 ],
|
||||
[ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 1.625 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 1.375 ],
|
||||
[ [ [ 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.75 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.625 ],
|
||||
[ [ [ 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.5 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.25 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.375 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.625 ],
|
||||
[ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.375 ]
|
||||
],
|
||||
[
|
||||
[ [ [ -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 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0 ],
|
||||
[ [ [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 1.375 ],
|
||||
[ [ [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 1.625 ],
|
||||
[ [ [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 0 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 0 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 1, 0 ] ], 1.5 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 1.5 ]
|
||||
],
|
||||
[
|
||||
[ [ [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 0 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, 0, 0, -2, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 1, -1, 0, 0, 0, 0 ] ], 0.625 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, 0, 0, -2, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 1, -1, 0 ] ], 1.375 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, 0, 0, -2, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, -1, 1 ] ], 0.625 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, 0, 0, -2, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 1, 0, 0, -1, 0 ] ], 1.875 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, 0, 0, -2, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0 ],
|
||||
[ [ [ "Rest" ], [ 1, -1, 0, 0, -1, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.375 ],
|
||||
[ [ [ "Rest" ], [ 1, -1, 0, 0, -1, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, -2, 0 ] ], 0 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, 0, 0, -1, -1 ], [ 1, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, -2, 0 ] ], 1.75 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, 0, -1, -1, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, -2, 0 ] ], 1.875 ]
|
||||
],
|
||||
[
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ 1, 0, 0, -1, -1, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ 1, 0, 0, 0, -2, 0 ] ], 1.125 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ 1, 0, 0, -1, -1, 0 ], [ 1, 0, 0, 0, -1, 0 ], [ -1, 0, 1, 0, 0, 1 ] ], 0 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, -1, 0, 1 ], [ 1, 0, 0, 0, -1, 0 ], [ -1, 0, 1, 0, 0, 1 ] ], 1.875 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, -1, 0, 1 ], [ -1, 0, 0, 1, 0, 1 ], [ -1, 0, 1, 0, 0, 1 ] ], 1.5 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, -1, 0, 1 ], [ 0, 0, -1, 0, 0, 1 ], [ -1, 0, 1, 0, 0, 1 ] ], 0 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, -1, 0, 1 ], [ 0, 0, -1, 0, 0, 1 ], [ 0, -1, 0, 0, 0, 1 ] ], 0.75 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, -1, 0, 1 ], [ 0, 0, -1, 0, 0, 1 ], [ -1, 1, 0, 0, 0, 1 ] ], 0 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ -1, 0, 1, 0, 0, 1 ], [ 0, 0, -1, 0, 0, 1 ], [ -1, 1, 0, 0, 0, 1 ] ], 1.75 ]
|
||||
],
|
||||
[
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ -1, 0, 1, 0, 0, 1 ], [ 0, 0, -1, 0, 0, 1 ], [ "Rest" ] ], 0 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ -1, 0, 1, 0, 0, 1 ], [ -1, 0, 1, 0, 1, 1 ], [ "Rest" ] ], 1.25 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ -1, 0, 1, 0, 0, 1 ], [ -1, 0, 0, 0, 0, 2 ], [ "Rest" ] ], 1.5 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ -1, 0, 1, 0, 0, 1 ], [ 0, 0, 0, 0, -1, 1 ], [ "Rest" ] ], 1.75 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ -1, 0, 1, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0.75 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ -1, 0, 1, 0, 0, 1 ], [ 0, -1, 0, 0, 0, 1 ], [ "Rest" ] ], 1.75 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ -1, 0, 1, 0, 0, 1 ], [ "Rest" ], [ "Rest" ] ], 1 ],
|
||||
[ [ [ -1, 0, 0, 0, 0, 1 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0.75 ],
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.25 ]
|
||||
]
|
||||
]
|
||||
],
|
||||
"last_changes":
|
||||
[
|
||||
[ [ -1, 0, 0, 0, 0, 1 ], [ -1, 0, 1, 0, 0, 1 ], [ -1, 0, 1, 0, 1, 1 ], [ -1, 1, 0, 0, 0, 1 ] ],
|
||||
[ [ -1, 0, 0, 0, 0, 1 ], [ -1, 0, 1, 0, 0, 1 ], [ -1, 0, 0, 0, 0, 2 ], [ -1, 1, 0, 0, 0, 1 ] ],
|
||||
[ [ -1, 0, 0, 0, 0, 1 ], [ -1, 0, 1, 0, 0, 1 ], [ 0, 0, 0, 0, -1, 1 ], [ -1, 1, 0, 0, 0, 1 ] ],
|
||||
[ [ -1, 0, 0, 0, 0, 1 ], [ -1, 0, 1, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 1 ] ],
|
||||
[ [ -1, 0, 0, 0, 0, 1 ], [ -1, 0, 1, 0, 0, 1 ], [ 0, -1, 0, 0, 0, 1 ], [ -1, 1, 0, 0, 0, 1 ] ]
|
||||
],
|
||||
"cur_uid": "62b894e8",
|
||||
"ref_uid": "nil",
|
||||
"order_seed": 684642,
|
||||
"dur_seed": 712392,
|
||||
"motifs_seed": 330807,
|
||||
"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":
|
||||
[
|
||||
[ [ 3, 1, 0 ], [ 2, 2, 2, 2, 2, 2, 2 ], [ ] ],
|
||||
[ [ 1 ], [ 0, 3, 2, 3, 3, 0, 2, 3 ], [ ] ],
|
||||
[ [ 2 ], [ 1, 3, 3, 3, 3, 1, 3, 1, 1 ], [ 0 ] ],
|
||||
[ [ 0 ], [ 3, 1, 2, 2, 3, 3, 1 ], [ ] ],
|
||||
[ [ 1, 0 ], [ 2, 2, 2, 2, 2 ], [ 3 ] ]
|
||||
],
|
||||
"sus_weights": [ 0.75, 0.69, 0.75 ],
|
||||
"order_size": [ 2, 6 ],
|
||||
"passages_size": [ 0, 10 ]
|
||||
}
|
@ -0,0 +1,716 @@
|
||||
(
|
||||
// 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, {
|
||||
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;
|
||||
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]).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 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, dFormat, condition, 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;
|
||||
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;
|
||||
|
||||
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.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});
|
||||
ledger.postln;
|
||||
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 ++ "_mus_model" ++ ".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");
|
@ -0,0 +1,38 @@
|
||||
{
|
||||
"music_data":
|
||||
[
|
||||
[
|
||||
[
|
||||
[ [ [ "Rest" ], [ 1, 0, 0, -1, -1, 0 ], [ "Rest" ], [ "Rest" ] ], 3.125 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, 0, -1, -1, 0 ], [ "Rest" ], [ 2, 0, 0, -2, -1, 0 ] ], 2.25 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, 0, -1, -1, 0 ], [ "Rest" ], [ "Rest" ] ], 2.625 ],
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 2 ]
|
||||
]
|
||||
]
|
||||
],
|
||||
"last_changes":
|
||||
[
|
||||
[ [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ],
|
||||
[ [ 0, 1, 0, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ],
|
||||
[ [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ],
|
||||
[ [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ],
|
||||
[ [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 2, 0, 0, -2, -1, 0 ] ]
|
||||
],
|
||||
"cur_uid": "640eeed3",
|
||||
"ref_uid": "4c01589b",
|
||||
"order_seed": 155513,
|
||||
"dur_seed": 460216,
|
||||
"motifs_seed": 397643,
|
||||
"entrances_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 ],
|
||||
"passages_probs_vals": [ 0, 1.87, 3.7996946564886, 0, 0.5, 0.5, 0.5, 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":
|
||||
[
|
||||
[ [ 1 ], [ 3 ], [ 0, 2 ] ]
|
||||
],
|
||||
"sus_weights": [ 1, 0, 0 ],
|
||||
"order_size": [ 1, 3 ],
|
||||
"passages_size": [ 0, 2 ]
|
||||
}
|
@ -0,0 +1,734 @@
|
||||
(
|
||||
// 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"});
|
||||
"\"" ++ 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, {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");
|
@ -0,0 +1,46 @@
|
||||
{
|
||||
"music_data":
|
||||
[
|
||||
[
|
||||
[
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 1 ],
|
||||
[ [ [ "Rest" ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0 ],
|
||||
[ [ [ "Rest" ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0.75 ]
|
||||
],
|
||||
[
|
||||
[ [ [ "Rest" ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0.875 ],
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ "Rest" ] ], 0.75 ],
|
||||
[ [ [ 0, 1, 0, 0, 0, 0 ], [ "Rest" ], [ 0, 1, 0, 0, 0, -1 ], [ "Rest" ] ], 1 ],
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ 0, 1, 0, 0, 0, -1 ], [ "Rest" ] ], 0 ],
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 0.625 ]
|
||||
]
|
||||
]
|
||||
],
|
||||
"last_changes":
|
||||
[
|
||||
[ [ 0, 1, 0, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ],
|
||||
[ [ 0, 1, 0, 0, 0, 0 ], [ 1, 0, 0, -1, -1, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ],
|
||||
[ [ 0, 1, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ],
|
||||
[ [ 0, 1, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ],
|
||||
[ [ 0, 1, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 1, 0, 0, 0, -1 ], [ 1, 0, 0, 0, 0, -1 ] ]
|
||||
],
|
||||
"cur_uid": "7aa8c429",
|
||||
"ref_uid": "4c01589b",
|
||||
"order_seed": 367527,
|
||||
"dur_seed": 393265,
|
||||
"motifs_seed": 960266,
|
||||
"entrances_probs_vals": [ 0.75, 0.5, 2, 0, 0.5, 0.5, 0.5, 1, 0.5 ],
|
||||
"passages_probs_vals": [ 0.75, 0.5, 2, 0, 0.5, 0.5, 0.5, 1, 0.5 ],
|
||||
"exits_probs_vals": [ 0.75, 0.5, 2, 0, 0.5, 0.5, 0.5, 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 ], [ 1, 3 ], [ 0 ] ],
|
||||
[ [ 0 ], [ 2 ], [ 3, 1 ] ]
|
||||
],
|
||||
"sus_weights": [ 1, 0, 0 ],
|
||||
"order_size": [ 1, 3 ],
|
||||
"passages_size": [ 0, 2 ]
|
||||
}
|
@ -0,0 +1,719 @@
|
||||
(
|
||||
// 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");
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,59 @@
|
||||
{
|
||||
"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 ]
|
||||
}
|
@ -0,0 +1,718 @@
|
||||
(
|
||||
// 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");
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,79 @@
|
||||
{
|
||||
"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 ]
|
||||
}
|
@ -0,0 +1,734 @@
|
||||
(
|
||||
// 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"});
|
||||
"\"" ++ 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, {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");
|
@ -0,0 +1,77 @@
|
||||
{
|
||||
"music_data":
|
||||
[
|
||||
[
|
||||
[
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 2, 0, 0, -1, 0, 0 ] ], 0 ],
|
||||
[ [ [ "Rest" ], [ 2, -1, 0, -1, 0, 0 ], [ "Rest" ], [ 2, 0, 0, -1, 0, 0 ] ], 0.625 ],
|
||||
[ [ [ "Rest" ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.875 ],
|
||||
[ [ [ 0, -1, 2, 0, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 0.75 ],
|
||||
[ [ [ 2, -2, 0, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 0.75 ],
|
||||
[ [ [ 2, -1, 0, -1, -1, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.125 ],
|
||||
[ [ [ 1, -1, 0, -1, 0, 1 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.75 ],
|
||||
[ [ [ 1, -2, 1, 0, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 0.5 ],
|
||||
[ [ [ 1, 0, 0, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.5 ],
|
||||
[ [ [ 2, -1, -1, -1, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.125 ],
|
||||
[ [ [ 0, 0, 1, 0, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.625 ],
|
||||
[ [ [ 0, -1, 1, 0, 1, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.75 ],
|
||||
[ [ [ 1, -1, 0, -1, 0, 1 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 2, 0, 0, -1, 0, 0 ] ], 1.625 ]
|
||||
],
|
||||
[
|
||||
[ [ [ 1, -1, 0, -1, 0, 1 ], [ 2, -1, 0, -1, 0, 0 ], [ "Rest" ], [ 2, 0, 0, -1, 0, 0 ] ], 0 ],
|
||||
[ [ [ 1, -1, 0, -1, 0, 1 ], [ 2, -1, 0, -1, 0, 0 ], [ "Rest" ], [ 2, -1, 0, -1, 0, 1 ] ], 0 ],
|
||||
[ [ [ 1, -1, 0, -1, 0, 1 ], [ 2, -2, 0, -1, 0, 1 ], [ "Rest" ], [ 2, -1, 0, -1, 0, 1 ] ], 1.125 ],
|
||||
[ [ [ 1, -1, 0, -1, 0, 1 ], [ 2, -2, 0, -1, 0, 1 ], [ "Rest" ], [ 1, -1, 0, 0, 0, 1 ] ], 0.875 ],
|
||||
[ [ [ 1, -1, 0, -1, 0, 1 ], [ 1, -1, 1, -1, 0, 1 ], [ "Rest" ], [ 1, -1, 0, 0, 0, 1 ] ], 0 ],
|
||||
[ [ [ 1, -1, 0, -1, 0, 1 ], [ 1, -1, 1, -1, 0, 1 ], [ "Rest" ], [ 1, -1, 0, -1, 0, 2 ] ], 0.75 ],
|
||||
[ [ [ 1, -1, 0, -1, 0, 1 ], [ 2, -1, 0, -2, 0, 1 ], [ "Rest" ], [ 1, -1, 0, -1, 0, 2 ] ], 1.25 ],
|
||||
[ [ [ 1, -1, 0, -1, 0, 1 ], [ 2, -1, 0, -1, 0, 0 ], [ "Rest" ], [ 1, -1, 0, -1, 0, 2 ] ], 1.75 ]
|
||||
],
|
||||
[
|
||||
[ [ [ 1, -1, 0, -1, 0, 1 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 2 ] ], 1.625 ],
|
||||
[ [ [ 0, 0, 1, 0, 0, 0 ], [ 2, -1, 0, -1, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 2 ] ], 0 ],
|
||||
[ [ [ 0, 0, 1, 0, 0, 0 ], [ 0, -1, 1, 0, 0, 1 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 2 ] ], 0.625 ],
|
||||
[ [ [ 0, -1, 1, -1, 0, 2 ], [ 0, -1, 1, 0, 0, 1 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 2 ] ], 0.625 ],
|
||||
[ [ [ 0, -1, 1, 0, 1, 0 ], [ 0, -1, 1, 0, 0, 1 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 2 ] ], 0 ],
|
||||
[ [ [ 0, -1, 1, 0, 1, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 2 ] ], 1.5 ],
|
||||
[ [ [ 0, -1, 1, 0, 1, 0 ], [ 1, -2, 1, 0, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 2 ] ], 0.75 ],
|
||||
[ [ [ 1, -1, 1, 0, -1, 0 ], [ 1, -2, 1, 0, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 2 ] ], 1.25 ],
|
||||
[ [ [ 1, -1, 1, 0, -1, 0 ], [ -1, -1, 0, 0, 0, 2 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 2 ] ], 1.75 ],
|
||||
[ [ [ 1, -1, 0, -1, 0, 1 ], [ -1, -1, 0, 0, 0, 2 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 2 ] ], 0 ],
|
||||
[ [ [ 1, -1, 0, -1, 0, 1 ], [ 0, -1, -1, -1, 0, 2 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 2 ] ], 0.75 ],
|
||||
[ [ [ 1, -1, 0, -1, 0, 1 ], [ -1, 0, 0, -1, 0, 2 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 2 ] ], 1.25 ],
|
||||
[ [ [ 1, -1, 0, -1, 0, 1 ], [ -1, 0, 0, -1, 0, 2 ], [ "Rest" ], [ 1, -1, 0, -1, 0, 2 ] ], 0 ],
|
||||
[ [ [ 1, -1, 0, -1, 0, 1 ], [ "Rest" ], [ "Rest" ], [ 1, -1, 0, -1, 0, 2 ] ], 0.75 ],
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 1, -1, 0, -1, 0, 2 ] ], 0 ],
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.875 ]
|
||||
]
|
||||
]
|
||||
],
|
||||
"last_changes":
|
||||
[
|
||||
[ [ 1, -1, 1, 0, -1, 0 ], [ 1, -2, 1, 0, 0, 0 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 2 ] ],
|
||||
[ [ 1, -1, 1, 0, -1, 0 ], [ -1, -1, 0, 0, 0, 2 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 2 ] ],
|
||||
[ [ 1, -1, 0, -1, 0, 1 ], [ -1, -1, 0, 0, 0, 2 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 2 ] ],
|
||||
[ [ 1, -1, 0, -1, 0, 1 ], [ 0, -1, -1, -1, 0, 2 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 2 ] ],
|
||||
[ [ 1, -1, 0, -1, 0, 1 ], [ -1, 0, 0, -1, 0, 2 ], [ 1, -1, 1, 0, 0, 0 ], [ 1, -1, 0, -1, 0, 2 ] ]
|
||||
],
|
||||
"cur_uid": "7ead41c3",
|
||||
"ref_uid": "46b6952a",
|
||||
"order_seed": 941210,
|
||||
"dur_seed": 186474,
|
||||
"motifs_seed": 450931,
|
||||
"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":
|
||||
[
|
||||
[ [ 3, 1, 2 ], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], [ ] ],
|
||||
[ [ 0 ], [ 3, 1, 3, 1, 3, 1, 1 ], [ 2 ] ],
|
||||
[ [ 2, 3 ], [ 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1 ], [ ] ]
|
||||
],
|
||||
"sus_weights": [ 0.75, 0.69, 0.75 ],
|
||||
"order_size": [ 2, 6 ],
|
||||
"passages_size": [ 0, 10 ]
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
{
|
||||
"ledger":
|
||||
[
|
||||
"4c01589b",
|
||||
"7e170ef8",
|
||||
"46b6952a",
|
||||
"7ac10d34",
|
||||
"640eeed3",
|
||||
"5e947063",
|
||||
"5cf1e9ab",
|
||||
"7aa8c429",
|
||||
"7ead41c3",
|
||||
"62b894e8",
|
||||
"628d5c8b",
|
||||
"55930f4d"
|
||||
]
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
{
|
||||
"ledger":
|
||||
[
|
||||
"4c01589b",
|
||||
"7e170ef8",
|
||||
"46b6952a",
|
||||
"7ac10d34",
|
||||
"640eeed3",
|
||||
"5e947063",
|
||||
"5cf1e9ab",
|
||||
"7aa8c429",
|
||||
"7ead41c3",
|
||||
"62b894e8",
|
||||
"628d5c8b"
|
||||
]
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
{
|
||||
ledger:
|
||||
[
|
||||
314491,
|
||||
314491,
|
||||
314491,
|
||||
314491,
|
||||
127947,
|
||||
389839,
|
||||
333441,
|
||||
175649,
|
||||
936089,
|
||||
936089,
|
||||
947477,
|
||||
947477
|
||||
]
|
||||
}
|
@ -0,0 +1,603 @@
|
||||
{
|
||||
"mus_seq": "[\n [\n [\n [ [ [ \"Rest\" ], [ \"Rest\" ], [ \"Rest\" ], [ 0, 0, 0, 0, 0, 0 ] ], 0 ], \n [ [ [ \"Rest\" ], [ \"Rest\" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.75 ], \n [ [ [ 0, 0, 1, 0, 0, 0 ], [ \"Rest\" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.5 ], \n [ [ [ 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.75 ], \n [ [ [ 0, 0, 1, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0.5 ], \n [ [ [ 0, 0, 1, 0, 0, 0 ], [ -1, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.875 ], \n [ [ [ 0, 0, 1, 0, 0, 0 ], [ 0, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.625 ], \n [ [ [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0 ], \n [ [ [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.5 ]\n ],\n [\n [ [ [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.125 ], \n [ [ [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 1, 0, -1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1 ], \n [ [ [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, -1, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0.875 ], \n [ [ [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0.75 ], \n [ [ [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ 0, 0, 0, -1, 0, 1 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.625 ], \n [ [ [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ -1, 0, 1, 0, 1, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.75 ], \n [ [ [ 0, 0, 0, 0, 1, 0 ], [ 1, 0, 0, -1, 0, 0 ], [ -1, 0, 1, 0, 1, 0 ], [ \"Rest\" ] ], 0 ], \n [ [ [ \"Rest\" ], [ 1, 0, 0, -1, 0, 0 ], [ -1, 0, 1, 0, 1, 0 ], [ \"Rest\" ] ], 0 ], \n [ [ [ \"Rest\" ], [ \"Rest\" ], [ -1, 0, 1, 0, 1, 0 ], [ \"Rest\" ] ], 0 ], \n [ [ [ \"Rest\" ], [ \"Rest\" ], [ \"Rest\" ], [ \"Rest\" ] ], 1.375 ]\n ]\n ]\n]",
|
||||
"motif_label": "motif",
|
||||
"motif_panel": -1,
|
||||
"seeds_label": "seeds",
|
||||
"order": "[\n [ [ 3, 2 ], [ 0, 1, 1, 1, 1, 1, 0 ], [ ] ], \n [ [ 1, 0, 3 ], [ 2, 2, 2, 2, 2, 2 ], [ ] ]\n]",
|
||||
"order_lock": 0,
|
||||
"order_size_rslider": [
|
||||
2,
|
||||
6
|
||||
],
|
||||
"order_size_input_max": 6,
|
||||
"order_size_input_min": 2,
|
||||
"order_size": -1,
|
||||
"passages_size_rslider": [
|
||||
0,
|
||||
10
|
||||
],
|
||||
"passages_size_input_max": 10,
|
||||
"passages_size_input_min": 0,
|
||||
"passages_size": -1,
|
||||
"sus_weights": [
|
||||
null,
|
||||
null,
|
||||
null
|
||||
],
|
||||
"range_matrix": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
],
|
||||
"instrumentation": -1,
|
||||
"entrances_probs_sync": "entrances",
|
||||
"entrances": -1,
|
||||
"passages_probs_sync": "passages",
|
||||
"passages": -1,
|
||||
"exits_probs_sync": "exits",
|
||||
"exits": -1,
|
||||
"dur_panel": 0,
|
||||
"durations": -1,
|
||||
"passages_weights": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
],
|
||||
"weights": -1,
|
||||
"seeds_tab_panel": 1,
|
||||
"order_seed_lock": 0,
|
||||
"order_seed": 684642,
|
||||
"dur_seed_lock": 0,
|
||||
"dur_seed": 712392,
|
||||
"weights_seed_lock": 0,
|
||||
"weights_seed": 330807,
|
||||
"seeds_panel": -1,
|
||||
"root": -1,
|
||||
"sus_weights/0_val_slider": 0.75,
|
||||
"sus_weights/0_val_input": 0.75,
|
||||
"sus_weights/0_val_label": 1,
|
||||
"sus_weights/0_val": -1,
|
||||
"sus_weights/1_val_slider": 0.69,
|
||||
"sus_weights/1_val_input": 0.69,
|
||||
"sus_weights/1_val_label": 2,
|
||||
"sus_weights/1_val": -1,
|
||||
"sus_weights/2_val_slider": 0.75,
|
||||
"sus_weights/2_val_input": 0.75,
|
||||
"sus_weights/2_val_label": 3,
|
||||
"sus_weights/2_val": -1,
|
||||
"passages_weights/0_val_slider": 0.75,
|
||||
"passages_weights/0_val_input": 0.75,
|
||||
"passages_weights/0_val_label": "step",
|
||||
"passages_weights/0_val": -1,
|
||||
"passages_weights/1_val_slider": 0.75,
|
||||
"passages_weights/1_val_input": 0.75,
|
||||
"passages_weights/1_val_label": "dc",
|
||||
"passages_weights/1_val": -1,
|
||||
"passages_weights/2_val_slider": 0.75,
|
||||
"passages_weights/2_val_input": 0.75,
|
||||
"passages_weights/2_val_label": "range",
|
||||
"passages_weights/2_val": -1,
|
||||
"passages_weights/3_val_slider": 0.75,
|
||||
"passages_weights/3_val_input": 0.75,
|
||||
"passages_weights/3_val_label": "registration",
|
||||
"passages_weights/3_val": -1,
|
||||
"passages_weights/4_val_slider": 0.75,
|
||||
"passages_weights/4_val_input": 0.75,
|
||||
"passages_weights/4_val_label": "hd",
|
||||
"passages_weights/4_val": -1,
|
||||
"range_matrix/0_val_input_min": -384,
|
||||
"range_matrix/0_val_rslider": [
|
||||
-384,
|
||||
2400
|
||||
],
|
||||
"range_matrix/0_val_input_max": 2400,
|
||||
"range_matrix/0_val": -1,
|
||||
"range_matrix/1_val_input_min": -507,
|
||||
"range_matrix/1_val_rslider": [
|
||||
-507,
|
||||
2400
|
||||
],
|
||||
"range_matrix/1_val_input_max": 2400,
|
||||
"range_matrix/1_val": -1,
|
||||
"range_matrix/2_val_input_min": -282,
|
||||
"range_matrix/2_val_rslider": [
|
||||
-282,
|
||||
2237
|
||||
],
|
||||
"range_matrix/2_val_input_max": 2237,
|
||||
"range_matrix/2_val": -1,
|
||||
"range_matrix/3_val_input_min": -1200,
|
||||
"range_matrix/3_val_rslider": [
|
||||
-1200,
|
||||
2053
|
||||
],
|
||||
"range_matrix/3_val_input_max": 2053,
|
||||
"range_matrix/3_val": -1,
|
||||
"entrances_probs_chord_val_slider": 0.75,
|
||||
"entrances_probs_chord_val_input": 0.75,
|
||||
"entrances_probs_chord_val_label": "chord prob",
|
||||
"entrances_probs_chord_val": -1,
|
||||
"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
|
||||
],
|
||||
"entrances_probs": -1,
|
||||
"passages_probs_chord_val_slider": 0.75,
|
||||
"passages_probs_chord_val_input": 0.75,
|
||||
"passages_probs_chord_val_label": "chord prob",
|
||||
"passages_probs_chord_val": -1,
|
||||
"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
|
||||
],
|
||||
"passages_probs": -1,
|
||||
"exits_probs_chord_val_slider": 0.75,
|
||||
"exits_probs_chord_val_input": 0.75,
|
||||
"exits_probs_chord_val_label": "chord prob",
|
||||
"exits_probs_chord_val": -1,
|
||||
"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
|
||||
],
|
||||
"exits_probs": -1,
|
||||
"step_env_env_vals": [
|
||||
0.5,
|
||||
2,
|
||||
0,
|
||||
0.5,
|
||||
0.5,
|
||||
0.5,
|
||||
1,
|
||||
0.5
|
||||
],
|
||||
"step_env_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
|
||||
],
|
||||
"step_env_env_size": 3,
|
||||
"step_env_env_flatten": 0,
|
||||
"step_env_env_rslider": [
|
||||
0.5,
|
||||
2
|
||||
],
|
||||
"step_env_env_input_max": 2,
|
||||
"step_env_env_input_min": 0.5,
|
||||
"step_env_env_mpos": "",
|
||||
"step_env_env": -1,
|
||||
"entrances_probs_dur_env_vals": [
|
||||
0.5,
|
||||
2,
|
||||
0,
|
||||
0.5,
|
||||
0.26424870466321,
|
||||
0.75675675675676,
|
||||
0.5,
|
||||
0.5,
|
||||
0.58549222797927,
|
||||
0.72635135135135,
|
||||
1,
|
||||
0.5
|
||||
],
|
||||
"entrances_probs_dur_env_canvas": [
|
||||
[
|
||||
0,
|
||||
0.5
|
||||
],
|
||||
[
|
||||
0.26424870466321,
|
||||
0.75675675675676
|
||||
],
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
],
|
||||
[
|
||||
0.58549222797927,
|
||||
0.72635135135135
|
||||
],
|
||||
[
|
||||
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
|
||||
],
|
||||
"entrances_probs_dur_env_size": 5,
|
||||
"entrances_probs_dur_env_flatten": 0,
|
||||
"entrances_probs_dur_env_rslider": [
|
||||
0.5,
|
||||
2
|
||||
],
|
||||
"entrances_probs_dur_env_input_max": 2,
|
||||
"entrances_probs_dur_env_input_min": 0.5,
|
||||
"entrances_probs_dur_env_mpos": "",
|
||||
"entrances_probs_dur_env": -1,
|
||||
"passages_probs_dur_env_vals": [
|
||||
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
|
||||
],
|
||||
"passages_probs_dur_env_canvas": [
|
||||
[
|
||||
0,
|
||||
0.5
|
||||
],
|
||||
[
|
||||
0.20725388601036,
|
||||
0.68581081081081
|
||||
],
|
||||
[
|
||||
0.24093264248705,
|
||||
0.34121621621622
|
||||
],
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
],
|
||||
[
|
||||
0.67616580310881,
|
||||
0.81081081081081
|
||||
],
|
||||
[
|
||||
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
|
||||
],
|
||||
"passages_probs_dur_env_size": 6,
|
||||
"passages_probs_dur_env_flatten": 0,
|
||||
"passages_probs_dur_env_rslider": [
|
||||
0.5,
|
||||
2
|
||||
],
|
||||
"passages_probs_dur_env_input_max": 2,
|
||||
"passages_probs_dur_env_input_min": 0.5,
|
||||
"passages_probs_dur_env_mpos": "",
|
||||
"passages_probs_dur_env": -1,
|
||||
"exits_probs_dur_env_vals": [
|
||||
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_dur_env_canvas": [
|
||||
[
|
||||
0,
|
||||
0.5
|
||||
],
|
||||
[
|
||||
0.20725388601036,
|
||||
0.68581081081081
|
||||
],
|
||||
[
|
||||
0.24093264248705,
|
||||
0.34121621621622
|
||||
],
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
],
|
||||
[
|
||||
0.67616580310881,
|
||||
0.81081081081081
|
||||
],
|
||||
[
|
||||
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
|
||||
],
|
||||
"exits_probs_dur_env_size": 6,
|
||||
"exits_probs_dur_env_flatten": 0,
|
||||
"exits_probs_dur_env_rslider": [
|
||||
0.5,
|
||||
2
|
||||
],
|
||||
"exits_probs_dur_env_input_max": 2,
|
||||
"exits_probs_dur_env_input_min": 0.5,
|
||||
"exits_probs_dur_env_mpos": "",
|
||||
"exits_probs_dur_env": -1
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
{
|
||||
"music_data":
|
||||
[
|
||||
[
|
||||
[
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ] ], 1.75 ],
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 4.625 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 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 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 0.875 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 4.5 ]
|
||||
],
|
||||
[
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ], 1.375 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 1, 0, 0 ] ], 1.25 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ -1, 0, 0, 0, 0, 1 ] ], 1.875 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, -1, -1, 0, 0 ] ], 1.875 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 1.625 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, -1, 0, 1, 0 ] ], 0.5 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ] ], 1.875 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, -1, 0, 0 ] ], 0.75 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 1.875 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0, -1 ] ], 0.875 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 4.375 ]
|
||||
],
|
||||
[
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 0, 0, -1, 0, 1, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 1 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ 1, -1, -1, 0, 1, 0 ], [ 0, 0, -1, 0, 1, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 1.5 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 0, 0, -1, 0, 1, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 0.625 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 1 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, 0, -1, 0, -1, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 1.75 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, 0, 0, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 1.25 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 2, -1, -1, 0, 0, -1 ], [ 1, -1, -1, 0, 0, 0 ] ], 0.75 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, -1, -1, 0, 1, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 1.625 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ 1, 0, -2, 0, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 3.375 ]
|
||||
],
|
||||
[
|
||||
[ [ [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ], [ 1, 0, -2, 0, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 1.125 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ], [ 0, 0, -1, 1, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 0.75 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ], [ 0, 1, -1, 0, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 0.875 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 0.625 ],
|
||||
[ [ [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ], [ 1, 0, -1, 0, -1, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 3.625 ]
|
||||
],
|
||||
[
|
||||
[ [ [ "Rest" ], [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 1, -1, -1, 0, 0, 0 ] ], 2 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ 1, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 1, -1, -1, 0, 0, 0 ] ], 0 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ 2, -1, -2, 0, 0, 0 ], [ "Rest" ], [ 1, -1, -1, 0, 0, 0 ] ], 5 ]
|
||||
],
|
||||
[
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 1, -1, -1, 0, 0, 0 ] ], 1.125 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 0, -1, 0, -1, 0 ], [ 1, -1, -1, 0, 0, 0 ] ], 1 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 0, -1, 0, -1, 0 ], [ 0, 0, -1, 0, 1, 0 ] ], 1.875 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 0, -1, 0, -1, 0 ], [ 0, 1, -1, 0, 0, 0 ] ], 1.125 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 0, -1, 0, -1, 0 ], [ 1, 0, -2, 0, 0, 0 ] ], 1.875 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 0, -1, 0, -1, 0 ], [ 0, 0, -1, 0, 0, 1 ] ], 0.625 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ 1, 0, -1, 0, -1, 0 ], [ 0, 0, -1, 1, 0, 0 ] ], 4.25 ]
|
||||
],
|
||||
[
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 0, 0, -1, 1, 0, 0 ] ], 1.25 ],
|
||||
[ [ [ 0, 0, -1, 0, 0, 0 ], [ 2, -1, -2, 0, 0, 0 ], [ "Rest" ], [ 0, 0, -1, 1, 0, 0 ] ], 1 ],
|
||||
[ [ [ 1, -1, -2, 0, 0, 0 ], [ 2, -1, -2, 0, 0, 0 ], [ "Rest" ], [ 0, 0, -1, 1, 0, 0 ] ], 1.875 ],
|
||||
[ [ [ 0, -1, -2, 1, 0, 0 ], [ 2, -1, -2, 0, 0, 0 ], [ "Rest" ], [ 0, 0, -1, 1, 0, 0 ] ], 3.125 ]
|
||||
],
|
||||
[
|
||||
[ [ [ 0, -1, -2, 1, 0, 0 ], [ 2, -1, -2, 0, 0, 0 ], [ 1, 0, -1, 0, -1, 0 ], [ 0, 0, -1, 1, 0, 0 ] ], 3.75 ],
|
||||
[ [ [ 0, -1, -2, 1, 0, 0 ], [ 1, 0, -1, 0, -1, 1 ], [ 1, 0, -1, 0, -1, 0 ], [ 0, 0, -1, 1, 0, 0 ] ], 1.375 ],
|
||||
[ [ [ 0, -1, -2, 1, 0, 0 ], [ 1, 0, -1, 0, -1, 1 ], [ 1, 0, -1, 0, -1, 0 ], [ 1, 0, 0, 0, -1, 0 ] ], 0.75 ],
|
||||
[ [ [ 0, -1, -2, 1, 0, 0 ], [ 1, 0, -1, 0, -1, 1 ], [ 1, 0, -1, 0, -1, 0 ], [ 1, -1, -2, 1, 0, 0 ] ], 1.5 ],
|
||||
[ [ [ 0, -1, -2, 1, 0, 0 ], [ 1, 0, -1, 0, -1, 1 ], [ 1, 0, -1, 0, -1, 0 ], [ 2, 0, -1, 0, -2, 0 ] ], 1 ],
|
||||
[ [ [ 0, -1, -2, 1, 0, 0 ], [ 1, 0, -1, 0, -1, 1 ], [ 1, 0, -1, 0, -1, 0 ], [ 2, -1, -2, 0, 0, 0 ] ], 1.125 ],
|
||||
[ [ [ 0, -1, -2, 1, 0, 0 ], [ 1, 0, -1, 0, -1, 1 ], [ 1, 0, -1, 0, -1, 0 ], [ 2, -1, -1, 0, -1, 0 ] ], 1.125 ],
|
||||
[ [ [ 0, -1, -2, 1, 0, 0 ], [ 1, 0, -1, 0, -1, 1 ], [ 1, 0, -1, 0, -1, 0 ], [ 2, 0, -1, 0, -1, -1 ] ], 5.25 ],
|
||||
[ [ [ 0, -1, -2, 1, 0, 0 ], [ 1, 0, -1, 0, -1, 1 ], [ "Rest" ], [ 2, 0, -1, 0, -1, -1 ] ], 0 ],
|
||||
[ [ [ 0, -1, -2, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ 2, 0, -1, 0, -1, -1 ] ], 1.5 ],
|
||||
[ [ [ 0, -1, -2, 1, 0, 0 ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 1.75 ],
|
||||
[ [ [ "Rest" ], [ "Rest" ], [ "Rest" ], [ "Rest" ] ], 4.625 ]
|
||||
]
|
||||
]
|
||||
],
|
||||
"last_changes":
|
||||
[
|
||||
[ [ 0, -1, -2, 1, 0, 0 ], [ 1, 0, -1, 0, -1, 1 ], [ 1, 0, -1, 0, -1, 0 ], [ 1, -1, -2, 1, 0, 0 ] ],
|
||||
[ [ 0, -1, -2, 1, 0, 0 ], [ 1, 0, -1, 0, -1, 1 ], [ 1, 0, -1, 0, -1, 0 ], [ 2, 0, -1, 0, -2, 0 ] ],
|
||||
[ [ 0, -1, -2, 1, 0, 0 ], [ 1, 0, -1, 0, -1, 1 ], [ 1, 0, -1, 0, -1, 0 ], [ 2, -1, -2, 0, 0, 0 ] ],
|
||||
[ [ 0, -1, -2, 1, 0, 0 ], [ 1, 0, -1, 0, -1, 1 ], [ 1, 0, -1, 0, -1, 0 ], [ 2, -1, -1, 0, -1, 0 ] ],
|
||||
[ [ 0, -1, -2, 1, 0, 0 ], [ 1, 0, -1, 0, -1, 1 ], [ 1, 0, -1, 0, -1, 0 ], [ 2, 0, -1, 0, -1, -1 ] ]
|
||||
],
|
||||
"cur_uid": "tmp",
|
||||
"ref_uid": "nil",
|
||||
"order_seed": 739163,
|
||||
"dur_seed": 513075,
|
||||
"motifs_seed": 310413,
|
||||
"entrances_probs_vals": [ 0.33687943262411, 1.91, 4.44, 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.33687943262411, 1.91, 4.44, 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.33687943262411, 1.91, 4.44, 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":
|
||||
[
|
||||
[ [ 3, 2 ], [ 0, 1, 1 ], [ ] ],
|
||||
[ [ 2, 0 ], [ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ], [ 1 ] ],
|
||||
[ [ 3, 0 ], [ 2, 1, 1, 2, 2, 2, 2, 2, 2 ], [ ] ],
|
||||
[ [ 3, 1 ], [ 2, 2, 2, 2 ], [ 0 ] ],
|
||||
[ [ 0, 3 ], [ 1 ], [ 2 ] ],
|
||||
[ [ 2, 0 ], [ 3, 3, 3, 3, 3 ], [ 1 ] ],
|
||||
[ [ 1, 3 ], [ 0, 0 ], [ 2 ] ],
|
||||
[ [ 0, 2 ], [ 1, 3, 3, 3, 3, 3, 3 ], [ ] ]
|
||||
],
|
||||
"sus_weights": [ 0, 0.82, 0 ],
|
||||
"order_size": [ 1, 10 ],
|
||||
"passages_size": [ 0, 10 ],
|
||||
"motif_edited": "false",
|
||||
"order_edited": "false"
|
||||
}
|
@ -0,0 +1,757 @@
|
||||
(
|
||||
// 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 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;
|
||||
|
||||
|
||||
// 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, 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",
|
||||
"motif_edited", "order_edited"
|
||||
];
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
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",
|
||||
"motif_edited", "order_edited"
|
||||
];
|
||||
|
||||
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,
|
||||
motifEdited, orderEdited = 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[..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;
|
||||
|
||||
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));
|
||||
//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");
|
@ -0,0 +1,727 @@
|
||||
(
|
||||
// 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;
|
||||
|
||||
// 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, model["dur_seed"]);
|
||||
};
|
||||
|
||||
genOrders = {arg minMotifLength = 1, maxMotifLength = 5, minProgLength = 0, maxProgLength = 5;
|
||||
((maxMotifLength - minMotifLength).rand + minMotifLength).collect({
|
||||
var noProgIns, noSusIns, noSilentIns, prog, sus, silent;
|
||||
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 ranges, stepScore, recentlySoundedScore, isInRangeScore, regScore, hdScore;
|
||||
|
||||
ranges = model["ranges"];
|
||||
//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 = model["passages_weights"];
|
||||
|
||||
//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 = [];
|
||||
|
||||
model["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, {
|
||||
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;
|
||||
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]).postln});
|
||||
model = Dictionary.with(*nameSpaces.collect({arg nS; nS -> msgInterpret.value(jsonObject[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 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, refUID, musPath, modelString;
|
||||
msg.postln;
|
||||
|
||||
path = msg[1].asString;
|
||||
|
||||
loadModelFile.value(path);
|
||||
|
||||
//refUID.postln;
|
||||
refUID = model["ref_uid"];
|
||||
|
||||
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"]);
|
||||
});
|
||||
|
||||
# entrancesDurFunc, passagesDurFunc, exitsDurFunc = ["entrances", "passages", "exits"].collect({arg nsPre;
|
||||
var probsVals = model[nsPre + "_probs_vals"];
|
||||
genDurFunc.valueArray(probsVals[..2] ++ [probsVals[3..]]);
|
||||
});
|
||||
|
||||
/*
|
||||
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, model["order_seed"]).valueArray(orderSize ++ passagesSize);
|
||||
//addr.sendMsg("/order", stringifyToDepth.value(orders, 1));
|
||||
});
|
||||
seq = seedFunc.value(genMotif, model["motif_seed"]).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;
|
||||
model["cur_uid"] = curUID;
|
||||
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});
|
||||
ledger.postln;
|
||||
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 ++ "_mus_model" ++ ".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");
|
@ -0,0 +1,324 @@
|
||||
(
|
||||
var formatMusicData, spellingDict, lyNoteNameStr, lyOctStr, lyFinalizeMusic, lyMeasureDef,
|
||||
lyRelMark, lyRelMarkNote, lyHBracket, lyStaffDef, lyTie,
|
||||
lyNoteName, lyCentDev, lyFreqRatio, lyDur, lyNote, lyBeamOpen, lyBeamClosed,
|
||||
consolidateNotes, consolidateRests,
|
||||
primes, hsArrayToFreq, hsArraysToFreqRatio;
|
||||
|
||||
primes = [[2, 1], [3, 2], [5, 4], [7, 4], [11, 8], [13, 8]];
|
||||
|
||||
hsArrayToFreq = {
|
||||
arg array;
|
||||
array.collect({arg dim, d; pow(primes[d][0]/primes[d][1], dim)}).product
|
||||
};
|
||||
|
||||
hsArraysToFreqRatio = {
|
||||
arg array1, array2;
|
||||
var fArray, num, den, gcd;
|
||||
fArray = array2 - array1;
|
||||
num = 1;
|
||||
den = 1;
|
||||
fArray.do({arg dim, d;
|
||||
if(dim > 0, {
|
||||
num = num * pow(primes[d][0], dim.abs);
|
||||
den = den * pow(primes[d][1], dim.abs);
|
||||
});
|
||||
if(dim < 0, {
|
||||
num = num * pow(primes[d][1], dim.abs);
|
||||
den = den * pow(primes[d][0], dim.abs);
|
||||
});
|
||||
});
|
||||
gcd = gcd(num.asInteger, den.asInteger);
|
||||
[num / gcd, den / gcd].asInteger
|
||||
};
|
||||
|
||||
// formats the data for the transcriber
|
||||
formatMusicData = {arg seq;
|
||||
var maxSize, voices, durs, baseData, musicData;
|
||||
maxSize = 0;
|
||||
# voices, durs = seq.flatten2(seq.maxDepth - 5).flop;
|
||||
|
||||
baseData = voices.flop.collect({arg voice, v;
|
||||
var clumps, hdScores, freqs, fDurs, refs;
|
||||
|
||||
//this gets the reference instrument and is another way to check things
|
||||
refs = voice.collect({arg item, i;
|
||||
var ref = [-1, [1, 1]];
|
||||
if((i > 0), {
|
||||
if((item != voice[i - 1]) && (item != ["Rest"]), {
|
||||
var ins;
|
||||
ins = voices[i].minIndex({arg hsArray, h;
|
||||
var res = 100000;
|
||||
if((h != v) && (hsArray != ["Rest"]), {res = (hsArray.drop(1) - item.drop(1)).abs.sum});
|
||||
res
|
||||
});
|
||||
if(voices[i][ins] != ["Rest"], {
|
||||
ref = [ins, hsArraysToFreqRatio.value(voices[i][ins], item)]
|
||||
}, {
|
||||
ref = [ins, [100, 100]]
|
||||
})
|
||||
});
|
||||
});
|
||||
ref
|
||||
});
|
||||
|
||||
clumps = voice.separate({arg a, b; a != b });
|
||||
freqs = clumps.collect({arg clump; if(clump[0] != ["Rest"], {(60.midicps * hsArrayToFreq.value(clump[0]))/*.cpsmidi.round(0.25).midicps*/}, {-1})});
|
||||
fDurs = durs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump.sum});
|
||||
refs = refs.clumps(clumps.collect({arg clump; clump.size})).collect({arg clump; clump[0]});
|
||||
[freqs, (fDurs / 0.125).round, refs].flop;
|
||||
});
|
||||
|
||||
musicData = baseData.collect({arg partData, p;
|
||||
var res;
|
||||
res = partData.collect({arg item, i;
|
||||
var freq, dur, ref, amp, sus, note;
|
||||
//# freq, dur, amp, mult, insRef = item;
|
||||
# freq, dur, ref = item;
|
||||
sus = dur.asInteger;
|
||||
note = sus.collect({[freq, ref, i]});
|
||||
//rest = if(p < rawMusicData.size, {(dur - sus).collect({[-1, -1, -1, i]})}, {[]});
|
||||
//note ++ rest
|
||||
note
|
||||
}).flatten;
|
||||
if(res.size > maxSize, {maxSize = res.size});
|
||||
res
|
||||
});
|
||||
|
||||
//make them all the same length
|
||||
maxSize = maxSize.trunc(64) + 64;
|
||||
musicData = musicData.collect({arg partData, p; partData.extend(maxSize, partData.last)});
|
||||
musicData
|
||||
};
|
||||
|
||||
// constants (spelling dictionary note names and octaves)
|
||||
spellingDict = Dictionary.with(*
|
||||
[
|
||||
\major -> Dictionary.with(*
|
||||
[0, 7, 2, 9, 4, 11].collect({arg pc; pc->\sharps}) ++
|
||||
[5, 10, 3, 8, 1, 6].collect({arg pc; pc->\flats})
|
||||
),
|
||||
\minor -> Dictionary.with(*
|
||||
[9, 4, 11, 6, 1, 8].collect({arg pc; pc->\sharps}) ++
|
||||
[2, 7, 0, 5, 10, 3].collect({arg pc; pc->\flats})
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
//define staff
|
||||
lyStaffDef = {arg name, nameShort, nameMidi;
|
||||
"\\new Staff = \"" ++ name ++ "\" \\with { \n" ++
|
||||
"instrumentName = \"" ++ name ++ "\" \n" ++
|
||||
"shortInstrumentName = \"" ++ nameShort ++ "\" \n" ++
|
||||
"midiInstrument = #\"" ++ nameMidi ++ "\" \n" ++
|
||||
"\n}\n"
|
||||
};
|
||||
|
||||
// add music preamble
|
||||
lyFinalizeMusic = {arg lyStr, part, name, nameShort, nameMidi, clef;
|
||||
"\\new StaffGroup \\with {\\remove \"System_start_delimiter_engraver\"}\n<<\n" ++
|
||||
lyStaffDef.value(name, nameShort, nameMidi) ++
|
||||
"<<\n\n{ " +
|
||||
"\n\\set Score.markFormatter = #format-mark-box-numbers " +
|
||||
"\\tempo 2 = 60\n" +
|
||||
"\\numericTimeSignature \\time 2/2\n" +
|
||||
"\\clef " ++ clef ++ "\n" ++ lyStr + "\\fermata" +
|
||||
" }>> \\bar \"|.\" \n} \n\n>>" ++
|
||||
"\n>>"
|
||||
};
|
||||
|
||||
// barline and ossia definition
|
||||
lyMeasureDef = {arg insName, part, beat;
|
||||
var barline = "|", break = "";
|
||||
barline = "\\bar \"|\"";
|
||||
if((beat % 16) == 0, {break = "\\break \\noPageBreak"});
|
||||
if((beat % (16 * 3)) == 0, {break = "\\pageBreak"});
|
||||
if(beat != 0, {"}\n>>\n" + barline + break}, {""}) + "\n<<\n" /*++ ossia*/ + "{"
|
||||
};
|
||||
|
||||
lyNoteNameStr = Dictionary.with(*
|
||||
[
|
||||
\sharps -> ["c", "cis", "d", "dis","e", "f", "fis", "g", "gis", "a", "ais", "b"],
|
||||
\flats -> ["c", "des", "d", "ees","e", "f", "ges", "g", "aes", "a", "bes", "b"],
|
||||
]
|
||||
);
|
||||
|
||||
lyOctStr = [",,", ",", "", "'", "''", "'''", "''''"];
|
||||
|
||||
lyTie = {"~"};
|
||||
|
||||
lyNoteName = {arg freq, spellingPref = \sharps;
|
||||
if(freq != -1, {
|
||||
lyNoteNameStr[spellingPref][((freq.cpsmidi).round(1) % 12)] ++
|
||||
lyOctStr[(((freq).cpsmidi).round(1) / 12).asInteger - 2];
|
||||
},{"r"});
|
||||
};
|
||||
|
||||
lyDur = {arg noteLength;
|
||||
switch(noteLength, 1, {"16"}, 2, {"8"}, 3, {"8."}, 4, {"4"});
|
||||
};
|
||||
|
||||
lyBeamOpen = {"["};
|
||||
|
||||
lyBeamClosed = {"]"};
|
||||
|
||||
lyCentDev = {arg freq, padding = true;
|
||||
var centDev;
|
||||
centDev = ((freq.cpsmidi - (freq.cpsmidi).round(1)) * 100).round(1).asInteger;
|
||||
"^\\markup { " ++ if(padding, {"\\pad-markup #0.2 \""}, {"\""}) ++
|
||||
if(centDev >= 0, {"+"}, {""}) ++ centDev.asString ++ "\"}"
|
||||
};
|
||||
|
||||
lyFreqRatio = {arg freqRatioMult, ref, padding = true, lower = 3, attachedToNote = true;
|
||||
var res, ratio;
|
||||
res = "\\markup {" + if(attachedToNote, {""}, {"\\normalsize"}) +
|
||||
"\\lower #" ++ lower + if(padding, {"\\pad-markup #0.2 "}, {" "});
|
||||
ratio = "\"" ++ freqRatioMult[0].asInteger ++ "/" ++ freqRatioMult[1].asInteger ++ "\" }";
|
||||
res = if(ref != nil,
|
||||
{
|
||||
res ++ "\\concat{ \"" ++ ["IV", "III", "II", "I"][ref] ++ "\"\\normal-size-super " ++ ratio ++ "}"
|
||||
}, {
|
||||
res ++ ratio
|
||||
}
|
||||
);
|
||||
if(attachedToNote, {"_" ++ res}, {res})
|
||||
};
|
||||
|
||||
lyNote = {arg freq, noteLength, freqRatioMult, ref, spellingPref = \sharps, addMarkup = true, frHide = false, padding = true;
|
||||
lyNoteName.value(freq, spellingPref) ++
|
||||
lyDur.value(noteLength) ++
|
||||
if(addMarkup, {
|
||||
"<MARKUP" ++
|
||||
lyCentDev.value(freq, padding) ++
|
||||
if(frHide, {""}, {lyFreqRatio.value(freqRatioMult, ref, padding)}) ++
|
||||
"MARKUP>"
|
||||
}, {""})
|
||||
};
|
||||
|
||||
consolidateNotes = {arg lyStr, part;
|
||||
var noteRegex, markupRegex, fullNoteRegex, restRegex, fullRestRegex, res;
|
||||
noteRegex = "(?<n>[a-g](?:es|is)?(?:[,']*?)?4)";
|
||||
markupRegex = if(part != 0, {"(<MARKUP.{75,85}MARKUP>)?"}, {"(<MARKUP.{75,115}MARKUP>)?"});
|
||||
fullNoteRegex = noteRegex ++ markupRegex ++ "(?:\\h+~\\h+\\k<n>)";
|
||||
restRegex = "(?<r>r4)";
|
||||
fullRestRegex = "(?<r>r4)(?:(\\h+)\\k<r>)";
|
||||
res = lyStr;
|
||||
[6, 4, 3, 2].do({arg len;
|
||||
[fullNoteRegex, fullRestRegex].do({arg regex;
|
||||
res.findRegexp(regex ++ "{" ++ (len-1) ++ "}").clump(3).do({arg match;
|
||||
var word, note, markup, lyDur;
|
||||
word = match[0][1];
|
||||
note = match[1][1];
|
||||
markup = match[2][1];
|
||||
lyDur = switch(len, 6, {"1."}, 4, {"1"}, 3, {"2."}, 2, {"2"});
|
||||
res = res.replace(word, note.replace("4", lyDur) ++ markup)});
|
||||
});
|
||||
});
|
||||
res.replace("<MARKUP", "").replace("MARKUP>", "");
|
||||
};
|
||||
|
||||
~transcribe = {arg rawMusicData;
|
||||
var basePath, scoreFile, musicData, insData, insNames, insNamesShort, insMidi, insClef;
|
||||
|
||||
basePath = thisProcess.nowExecutingPath.dirname +/+ "lilypond";
|
||||
basePath.mkdir;
|
||||
(basePath +/+ "includes").mkdir;
|
||||
|
||||
//scoreFile = File(basePath +/+ "tkam_score.ly".standardizePath,"w");
|
||||
//scoreFile.write(File.readAllString(basePath +/+ ".." +/+ "template" +/+ "tkam_score_template.ly").replace("seed: xxx", "seed: " ++ seed));
|
||||
//scoreFile.close;
|
||||
|
||||
musicData = formatMusicData.value(rawMusicData);
|
||||
|
||||
insData = [
|
||||
["IV", "IV", "clarinet", "bass"],
|
||||
["III", "III", "clarinet", "alto"],
|
||||
["II", "II", "clarinet", "treble"],
|
||||
["I", "I", "clarinet", "treble"]
|
||||
];
|
||||
|
||||
insNames = insData.slice(nil, 0);
|
||||
insNamesShort = insData.slice(nil, 1);
|
||||
insMidi = insData.slice(nil, 2);
|
||||
insClef = insData.slice(nil, 3);
|
||||
|
||||
musicData.do({arg part, p;
|
||||
var lyFile, lyStr, lastMusAtom, measureCount, spellingPref,
|
||||
tmpSectionData, pcRoot, partLookup, quality;
|
||||
|
||||
//create file
|
||||
lyFile = File((basePath +/+ "includes" +/+ "part_" ++ ["IV", "III", "II", "I"][p] ++ ".ly").standardizePath,"w");
|
||||
|
||||
//start lypond directives
|
||||
lyStr = "";
|
||||
lastMusAtom = nil;
|
||||
measureCount = 0;
|
||||
spellingPref = \sharps;
|
||||
tmpSectionData = nil;
|
||||
part.clump(4).do({arg beat, i;
|
||||
var gSum;
|
||||
gSum = 0;
|
||||
beat.separate({arg a, b;
|
||||
((a[0] != -1) || (b[0] != -1)) && (a != b)}).do({arg group, g;
|
||||
var noteLength, curMusAtom, freq, freqRatioMult, ref, isSame, isRest, isFirst, isLast,
|
||||
isTied, isMeasureBound, isBeamStart, isBeamEnd;
|
||||
|
||||
noteLength = group.size;
|
||||
gSum = gSum + noteLength;
|
||||
curMusAtom = group[0];
|
||||
freq = curMusAtom[0];
|
||||
//freqRatioMult = curMusAtom[1];
|
||||
ref = curMusAtom[1][0];
|
||||
freqRatioMult = curMusAtom[1][1];
|
||||
# isSame, isRest, isFirst, isLast = [curMusAtom == lastMusAtom, freq == -1, g == 0, gSum == 4];
|
||||
# isTied, isMeasureBound = [isSame && isRest.not, isFirst && ((i % 4) == 0)];
|
||||
# isBeamStart, isBeamEnd = [(noteLength != 4) && isFirst, (noteLength != 4) && isLast];
|
||||
|
||||
//add ties
|
||||
if(isTied, {lyStr = lyStr + lyTie.value});
|
||||
|
||||
//add barline and ossia definition
|
||||
//if(isMeasureBound, {lyStr = lyStr + "\\bar \"|.|\""}); //lyMeasureDef.value(sectionData[i], insNames[p], p, i)});
|
||||
if(isMeasureBound, {lyStr = lyStr + lyMeasureDef.value(insNames[p], p, i)});
|
||||
|
||||
//add note data
|
||||
/*
|
||||
if(sectionData[i] != nil, {
|
||||
tmpSectionData = sectionData[i];
|
||||
});
|
||||
if(isTied.not, {
|
||||
partLookup = if((p != 0) || [1, 2, 3].includes(ref).not , {p}, {ref});
|
||||
pcRoot = ((tmpSectionData[0][partLookup][3].cpsmidi).round(1) % 12).asInteger;
|
||||
quality = if(tmpSectionData[0][partLookup][1][2] == [[ 1, 5 ], [ 1, 2, 2 ]], {\major}, {\minor});
|
||||
spellingPref = spellingDict[quality][pcRoot];
|
||||
if(p == 0, {[(i / 4).asInteger, partLookup, pcRoot, quality]});
|
||||
});
|
||||
*/
|
||||
|
||||
//lyStr = lyStr + lyNote.value(freq, noteLength, freqRatioMult, ref, spellingPref, isSame.not && isRest.not);
|
||||
lyStr = lyStr + lyNote.value(freq, noteLength, freqRatioMult, ref, \sharps, isSame.not && isRest.not);
|
||||
|
||||
//beam group
|
||||
if(isBeamStart, {lyStr = lyStr ++ lyBeamOpen.value});
|
||||
if(isBeamEnd, {lyStr = lyStr ++ lyBeamClosed.value});
|
||||
|
||||
lastMusAtom = curMusAtom;
|
||||
});
|
||||
});
|
||||
|
||||
//wrap music and add staff definitions
|
||||
lyStr = lyFinalizeMusic.value(lyStr, p, insNames[p], insNamesShort[p], insMidi[p], insClef[p]);
|
||||
|
||||
//consolidate notes and rests
|
||||
lyStr = consolidateNotes.value(lyStr, p);
|
||||
|
||||
//write file
|
||||
lyFile.write(lyStr);
|
||||
lyFile.close;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
~transcribe.value(~seq);
|
||||
|
||||
)
|
Loading…
Reference in New Issue