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