«Graphical Tracker Functions» by Dindoléon

on 22 Jan'20 11:39 in guitrackerapi

Stores three functions inside global variables which can be used to create either a binary tracker, a probabilist tracker or a combination of these two inside the given view. The tracker is tied to an array referencing the probabilities for a given beat to have the note played. See internal documentation for more details and usage example at https://sccode.org/1-5cB . Note that the GUI is only used to modify an array, and therefore can be used for other purposes than a tracker.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
(
/*
Binary tracker has only 2 states : note will be playing, or won't. No randomness
Arguments are :
- Instance of Array, referencing the note's probability to be played. Can only be 0 and 1 here.
- Instance of UserView, where the tracker will be drawn
- Instance of Rect, coordinates where the tracker will be drawn
- Integer value defining the margin between tracker's buttons.
- Color value of the button when toggled. Untoggled is black.
*/
~add_binary_tracker = { | rythm_array, win, rect, margin, button_color |

	var button_width = rect.width - ( rythm_array.size + 1 * margin ) / ( rythm_array.size );

	for( 0, rythm_array.size - 1, { | i | // Add a button for every beat inside the rythm
		b = Button( win, Rect( rect.left + margin + ( margin + button_width * i ), rect.top + margin, button_width, rect.height - margin ) );
		b.states_( [
			[ "", Color.black, Color.black ], // Untoggled
			[ "", button_color, button_color ]  // Toggled
		] );
		b.action = { | button | rythm_array[ i ] = button.value }; // States are equal to the note's probability to be played.
		if( rythm_array[ i ] == 1, { b.value = 1 } ); // Checks if the rythm has toggled buttons at this point.
	} );

};

/*
Probabilist tracker potentially has an infinite number of states : probabilities are distributed in a linear fashion between a minimum and a maximum value, according to a number of steps.
Pushing the button will increment the probability, getting back to the minimum value if the maximum value was selected.
Arguments are :
- Instance of Array, referencing the note's probability to be played. Possibilities equal to the number of steps.
- Instance of UserView, where the tracker will be drawn
- Instance of Rect, coordinates where the tracker will be drawn
- Integer value defining the margin between tracker's buttons.
- Array of color values, will colorize the button when toggled, depending on the note's probabilty to played. Untoggled is black.
- Float value referencing the minimal probabilty for the note to be played
- Float value referencing the maximal probabilty for the note to be played
- Integer value referencing the number of probabilities values the button can trigger (thus the number of button states)
*/
~add_probabilist_tracker = { | rythm_array, win, rect, margin, button_colors, min_val, max_val, number_of_steps |

	var button_width = rect.width - ( rythm_array.size + 1 * margin ) / ( rythm_array.size );

	var steps = Array.interpolation( number_of_steps, min_val, max_val ); // Interpolation between min value and max value, returning an array which size is equal to the number of steps.

	var buttons_states = Array.fill( number_of_steps, { | i | [ "", Color.new( button_colors[ 0 ] * steps[ i ], button_colors[ 1 ] * steps[ i ], button_colors[ 2 ] * steps[ i ] ), Color.new( button_colors[ 0 ] * steps[ i ], button_colors[ 1 ] * steps[ i ], button_colors[ 2 ] * steps[ i ] ) ] } ); // For every available possibility, will add a button state, where the button color will be modulated by the probability ( lower probability is darker ).

	for( 0, rythm_array.size - 1, { | i |
		b = Button( win, Rect( rect.left + margin + ( margin + button_width * i ), rect.top + margin, button_width, rect.height - margin ) );

		b.states_( buttons_states );
		b.action = { | button | rythm_array[ i ] = steps[ button.value ] };

		for( 0, steps.size - 1, { | j | if( rythm_array[ i ].trunc(0.001) == steps[ j ].trunc(0.001), { b.value = j } ) } );
	} ); // Performs a check to see if a button states has been selected allready. Value is truncated to be compared, but if the array contains a value which cannot be compared with the available steps, button will be set as untoggled though sound will still have the indicated probability to be played.
};


/*
Duo tracker is a combination of the two trackers above. The top line is binary, usually used to configure the main rythmic pattern, the bottom line is probabilist, used to add random notes between the notes of the main pattern.
Pushing a top bottom will override the bottom button at this beat number. Identically, pushing the bottom button will disable the top button above.
Arguments are equivalent to the probabilist tracker.
*/
~add_duo_tracker = { | rythm_array, win, rect, margin, button_colors, min_val, max_val, number_of_steps |

	var button_width = rect.width - ( rythm_array.size + 1 * margin ) / ( rythm_array.size );
	var button_height = rect.height - ( 3 * margin ) / 2;
	var steps = Array.interpolation( number_of_steps, min_val, max_val );

	var buttons_states = Array.fill( number_of_steps - 1, { | i | [ "", Color.new( button_colors[ 0 ] * steps[ i ], button_colors[ 1 ] * steps[ i ], button_colors[ 2 ] * steps[ i ] ), Color.new( button_colors[ 0 ] * steps[ i ], button_colors[ 1 ] * steps[ i ], button_colors[ 2 ] * steps[ i ] ) ] } ); // For every available possibility, will add a button state, where the button color will be modulated by the probability ( lower probability is darker ).

	var classic_buttons = Array.fill( rythm_array.size, { Button( win ) } ); // Store the binary buttons inside an array.
	var probabilist_buttons = Array.fill( rythm_array.size, { Button( win ) } ); // Store the probabilist buttons inside an array.

	for( 0, classic_buttons.size - 1, { | i |

		classic_buttons[ i ].bounds = Rect( rect.left + margin + ( margin + button_width * i ), rect.top + margin, button_width, button_height );

		classic_buttons[ i ].states_( [
			[ "", Color.black, Color.black ],
			[ "", Color.new( button_colors[ 0 ], button_colors[ 1 ], button_colors[ 2 ] ), Color.new( button_colors[ 0 ], button_colors[ 1 ], button_colors[ 2 ] ) ]
		] );
		classic_buttons[ i ].action = { | button | rythm_array[ i ] = button.value; if( button.value == 1, { probabilist_buttons[ i ].value = 0 } ) };

		if( rythm_array[ i ] == max_val, { classic_buttons[ i ].value = 1 } );
	} );

	for( 0, probabilist_buttons.size - 1, { | i |

		probabilist_buttons[ i ].bounds = Rect( rect.left + margin + ( margin + button_width * i ), rect.top + ( margin * 2 ) + button_height, button_width, button_height );

		probabilist_buttons[ i ].states_( buttons_states );
		probabilist_buttons[ i ].action = { | button | rythm_array[ i ] = steps[ button.value ]; if( classic_buttons[ i ].value == 1, { classic_buttons[ i ].value = 0 } ) };

		for( 0, steps.size - 2, { | j | if( rythm_array[ i ].trunc(0.001) == steps[ j ].trunc(0.001), { probabilist_buttons[ i ].value = j } ) } );
	} );
};

)
raw 6566 chars (focus & ctrl+a+c to copy)
reception
comments