diff options
author | Bad Diode <bd@badd10de.dev> | 2024-01-15 16:06:05 +0100 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-01-15 16:06:05 +0100 |
commit | f6efcdd98b32f1cd0d5a4a52abb333437c04b44f (patch) | |
tree | f4542a21ceb080af21b684250650368de7fc9e3e /src | |
parent | 65089bc6ca9e31878afd583e133cb376ef03f268 (diff) | |
download | stepper-f6efcdd98b32f1cd0d5a4a52abb333437c04b44f.tar.gz stepper-f6efcdd98b32f1cd0d5a4a52abb333437c04b44f.zip |
[WIP] Add decay control and attack/decay params on ch3
Diffstat (limited to 'src')
-rw-r--r-- | src/assets.c | 4 | ||||
-rw-r--r-- | src/clipboard.c | 135 | ||||
-rw-r--r-- | src/drawing.c | 225 | ||||
-rw-r--r-- | src/main.c | 15 | ||||
-rw-r--r-- | src/patterns.c | 105 | ||||
-rw-r--r-- | src/sequencer.c | 42 |
6 files changed, 387 insertions, 139 deletions
diff --git a/src/assets.c b/src/assets.c index c11364e..be4b87c 100644 --- a/src/assets.c +++ b/src/assets.c | |||
@@ -97,8 +97,10 @@ enum WAVES { | |||
97 | 97 | ||
98 | typedef u32 Wave[WAVE_SIZE]; | 98 | typedef u32 Wave[WAVE_SIZE]; |
99 | static Wave wave_active = {0}; | 99 | static Wave wave_active = {0}; |
100 | static Wave wave_target = {0}; | 100 | // static Wave wave_target = {0}; |
101 | // TODO: wave env status: OFF, ATTACK, DECAY | ||
101 | static int wave_env_ticks = 0; | 102 | static int wave_env_ticks = 0; |
103 | static int wave_env_attack = 8; | ||
102 | static int wave_env_decay = 8; | 104 | static int wave_env_decay = 8; |
103 | 105 | ||
104 | static const Wave waves[][WAVE_VARS] = { | 106 | static const Wave waves[][WAVE_VARS] = { |
diff --git a/src/clipboard.c b/src/clipboard.c index d82f576..e92d4c5 100644 --- a/src/clipboard.c +++ b/src/clipboard.c | |||
@@ -37,20 +37,25 @@ clipboard_paste(void) { | |||
37 | case 0: { | 37 | case 0: { |
38 | pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; | 38 | pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; |
39 | pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; | 39 | pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; |
40 | send_notif("PASTED NOTE & PARAMS"); | ||
41 | } break; | 40 | } break; |
42 | case 1: { | 41 | case 1: { |
43 | pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; | 42 | pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; |
44 | pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; | 43 | pat_dst->ch2.params[trig_selection_loc].env_volume = pat_src->ch1.params[clipboard.src_trig].env_volume; |
45 | send_notif("PASTED NOTE & PARAMS"); | 44 | pat_dst->ch2.params[trig_selection_loc].env_time = pat_src->ch1.params[clipboard.src_trig].env_time; |
45 | pat_dst->ch2.params[trig_selection_loc].env_direction = pat_src->ch1.params[clipboard.src_trig].env_direction; | ||
46 | pat_dst->ch2.params[trig_selection_loc].duty_cycle = pat_src->ch1.params[clipboard.src_trig].duty_cycle; | ||
47 | pat_dst->ch2.params[trig_selection_loc].prob = pat_src->ch1.params[clipboard.src_trig].prob; | ||
48 | pat_dst->ch2.params[trig_selection_loc].pan = pat_src->ch1.params[clipboard.src_trig].pan; | ||
46 | } break; | 49 | } break; |
47 | case 2: { | 50 | case 2: { |
48 | pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; | 51 | pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; |
49 | send_notif("PASTED NOTE"); | 52 | pat_dst->ch3.params[trig_selection_loc].prob = pat_src->ch1.params[clipboard.src_trig].prob; |
53 | pat_dst->ch3.params[trig_selection_loc].pan = pat_src->ch1.params[clipboard.src_trig].pan; | ||
50 | } break; | 54 | } break; |
51 | case 3: { | 55 | case 3: { |
52 | pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; | 56 | pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; |
53 | send_notif("PASTED NOTE"); | 57 | pat_dst->ch4.params[trig_selection_loc].prob = pat_src->ch1.params[clipboard.src_trig].prob; |
58 | pat_dst->ch4.params[trig_selection_loc].pan = pat_src->ch1.params[clipboard.src_trig].pan; | ||
54 | } break; | 59 | } break; |
55 | } | 60 | } |
56 | } break; | 61 | } break; |
@@ -62,20 +67,22 @@ clipboard_paste(void) { | |||
62 | pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; | 67 | pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; |
63 | pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; | 68 | pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; |
64 | pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; | 69 | pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; |
65 | send_notif("PASTED NOTE & PARAMS"); | 70 | pat_dst->ch1.params[trig_selection_loc].prob = pat_src->ch2.params[clipboard.src_trig].prob; |
71 | pat_dst->ch1.params[trig_selection_loc].pan = pat_src->ch2.params[clipboard.src_trig].pan; | ||
66 | } break; | 72 | } break; |
67 | case 1: { | 73 | case 1: { |
68 | pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; | 74 | pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; |
69 | pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig]; | 75 | pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig]; |
70 | send_notif("PASTED NOTE & PARAMS"); | ||
71 | } break; | 76 | } break; |
72 | case 2: { | 77 | case 2: { |
73 | pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; | 78 | pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; |
74 | send_notif("PASTED NOTE"); | 79 | pat_dst->ch3.params[trig_selection_loc].prob = pat_src->ch2.params[clipboard.src_trig].prob; |
80 | pat_dst->ch3.params[trig_selection_loc].pan = pat_src->ch2.params[clipboard.src_trig].pan; | ||
75 | } break; | 81 | } break; |
76 | case 3: { | 82 | case 3: { |
77 | pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; | 83 | pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; |
78 | send_notif("PASTED NOTE"); | 84 | pat_dst->ch4.params[trig_selection_loc].prob = pat_src->ch2.params[clipboard.src_trig].prob; |
85 | pat_dst->ch4.params[trig_selection_loc].pan = pat_src->ch2.params[clipboard.src_trig].pan; | ||
79 | } break; | 86 | } break; |
80 | } | 87 | } |
81 | } break; | 88 | } break; |
@@ -83,20 +90,22 @@ clipboard_paste(void) { | |||
83 | switch (channel_selection_loc) { | 90 | switch (channel_selection_loc) { |
84 | case 0: { | 91 | case 0: { |
85 | pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; | 92 | pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; |
86 | send_notif("PASTED NOTE"); | 93 | pat_dst->ch1.params[trig_selection_loc].prob = pat_src->ch3.params[clipboard.src_trig].prob; |
94 | pat_dst->ch1.params[trig_selection_loc].pan = pat_src->ch3.params[clipboard.src_trig].pan; | ||
87 | } break; | 95 | } break; |
88 | case 1: { | 96 | case 1: { |
89 | pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; | 97 | pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; |
90 | send_notif("PASTED NOTE"); | 98 | pat_dst->ch2.params[trig_selection_loc].prob = pat_src->ch3.params[clipboard.src_trig].prob; |
99 | pat_dst->ch2.params[trig_selection_loc].pan = pat_src->ch3.params[clipboard.src_trig].pan; | ||
91 | } break; | 100 | } break; |
92 | case 2: { | 101 | case 2: { |
93 | pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; | 102 | pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; |
94 | pat_dst->ch3.params[trig_selection_loc] = pat_src->ch3.params[clipboard.src_trig]; | 103 | pat_dst->ch3.params[trig_selection_loc] = pat_src->ch3.params[clipboard.src_trig]; |
95 | send_notif("PASTED NOTE & PARAMS"); | ||
96 | } break; | 104 | } break; |
97 | case 3: { | 105 | case 3: { |
98 | pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; | 106 | pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; |
99 | send_notif("PASTED NOTE"); | 107 | pat_dst->ch4.params[trig_selection_loc].prob = pat_src->ch3.params[clipboard.src_trig].prob; |
108 | pat_dst->ch4.params[trig_selection_loc].pan = pat_src->ch3.params[clipboard.src_trig].pan; | ||
100 | } break; | 109 | } break; |
101 | } | 110 | } |
102 | } break; | 111 | } break; |
@@ -104,37 +113,44 @@ clipboard_paste(void) { | |||
104 | switch (channel_selection_loc) { | 113 | switch (channel_selection_loc) { |
105 | case 0: { | 114 | case 0: { |
106 | pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; | 115 | pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; |
107 | send_notif("PASTED NOTE"); | 116 | pat_dst->ch1.params[trig_selection_loc].prob = pat_src->ch4.params[clipboard.src_trig].prob; |
117 | pat_dst->ch1.params[trig_selection_loc].pan = pat_src->ch4.params[clipboard.src_trig].pan; | ||
108 | } break; | 118 | } break; |
109 | case 1: { | 119 | case 1: { |
110 | pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; | 120 | pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; |
111 | send_notif("PASTED NOTE"); | 121 | pat_dst->ch2.params[trig_selection_loc].prob = pat_src->ch4.params[clipboard.src_trig].prob; |
122 | pat_dst->ch2.params[trig_selection_loc].pan = pat_src->ch4.params[clipboard.src_trig].pan; | ||
112 | } break; | 123 | } break; |
113 | case 2: { | 124 | case 2: { |
114 | pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; | 125 | pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; |
115 | send_notif("PASTED NOTE"); | 126 | pat_dst->ch3.params[trig_selection_loc].prob = pat_src->ch4.params[clipboard.src_trig].prob; |
127 | pat_dst->ch3.params[trig_selection_loc].pan = pat_src->ch4.params[clipboard.src_trig].pan; | ||
116 | } break; | 128 | } break; |
117 | case 3: { | 129 | case 3: { |
118 | pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; | 130 | pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; |
119 | pat_dst->ch4.params[trig_selection_loc] = pat_src->ch4.params[clipboard.src_trig]; | 131 | pat_dst->ch4.params[trig_selection_loc] = pat_src->ch4.params[clipboard.src_trig]; |
120 | send_notif("PASTED NOTE & PARAMS"); | ||
121 | } break; | 132 | } break; |
122 | } | 133 | } |
123 | } break; | 134 | } break; |
124 | } | 135 | } |
136 | send_notif("PASTED NOTE & PARAMS"); | ||
125 | } | 137 | } |
126 | // Only paste the params for the respective trigger. | 138 | // Only paste the params for the respective trigger. |
127 | if (clipboard.type == CLIP_PARAM_CH1) { | 139 | if (clipboard.type == CLIP_PARAM_CH1) { |
128 | switch (channel_selection_loc) { | 140 | switch (channel_selection_loc) { |
129 | case 0: { | 141 | case 0: { |
130 | pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; | 142 | pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; |
131 | send_notif("PASTED PARAMS"); | ||
132 | } break; | 143 | } break; |
133 | case 1: { | 144 | case 1: { |
134 | pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; | 145 | pat_dst->ch2.params[trig_selection_loc].env_volume = pat_src->ch1.params[clipboard.src_trig].env_volume; |
135 | send_notif("PASTED PARAMS"); | 146 | pat_dst->ch2.params[trig_selection_loc].env_time = pat_src->ch1.params[clipboard.src_trig].env_time; |
147 | pat_dst->ch2.params[trig_selection_loc].env_direction = pat_src->ch1.params[clipboard.src_trig].env_direction; | ||
148 | pat_dst->ch2.params[trig_selection_loc].duty_cycle = pat_src->ch1.params[clipboard.src_trig].duty_cycle; | ||
149 | pat_dst->ch2.params[trig_selection_loc].prob = pat_src->ch1.params[clipboard.src_trig].prob; | ||
150 | pat_dst->ch2.params[trig_selection_loc].pan = pat_src->ch1.params[clipboard.src_trig].pan; | ||
136 | } break; | 151 | } break; |
137 | } | 152 | } |
153 | send_notif("PASTED PARAMS"); | ||
138 | } | 154 | } |
139 | if (clipboard.type == CLIP_PARAM_CH2) { | 155 | if (clipboard.type == CLIP_PARAM_CH2) { |
140 | switch (channel_selection_loc) { | 156 | switch (channel_selection_loc) { |
@@ -143,13 +159,14 @@ clipboard_paste(void) { | |||
143 | pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; | 159 | pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; |
144 | pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; | 160 | pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; |
145 | pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; | 161 | pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; |
146 | send_notif("PASTED PARAMS"); | 162 | pat_dst->ch1.params[trig_selection_loc].prob = pat_src->ch2.params[clipboard.src_trig].prob; |
163 | pat_dst->ch1.params[trig_selection_loc].pan = pat_src->ch2.params[clipboard.src_trig].pan; | ||
147 | } break; | 164 | } break; |
148 | case 1: { | 165 | case 1: { |
149 | pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig]; | 166 | pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig]; |
150 | send_notif("PASTED PARAMS"); | ||
151 | } break; | 167 | } break; |
152 | } | 168 | } |
169 | send_notif("PASTED PARAMS"); | ||
153 | } | 170 | } |
154 | if (clipboard.type == CLIP_PARAM_CH3 && channel_selection_loc == clipboard.src_chan) { | 171 | if (clipboard.type == CLIP_PARAM_CH3 && channel_selection_loc == clipboard.src_chan) { |
155 | pat_dst->ch3.params[trig_selection_loc] = pat_src->ch3.params[clipboard.src_trig]; | 172 | pat_dst->ch3.params[trig_selection_loc] = pat_src->ch3.params[clipboard.src_trig]; |
@@ -170,6 +187,8 @@ clipboard_paste(void) { | |||
170 | pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; | 187 | pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; |
171 | pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; | 188 | pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; |
172 | pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; | 189 | pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; |
190 | pat_dst->ch1.params[trig_selection_loc].prob = pat_src->ch2.params[clipboard.src_trig].prob; | ||
191 | pat_dst->ch1.params[trig_selection_loc].pan = pat_src->ch2.params[clipboard.src_trig].pan; | ||
173 | send_notif("PASTED PARAMS"); | 192 | send_notif("PASTED PARAMS"); |
174 | draw_parameters(); | 193 | draw_parameters(); |
175 | } else if (input_handler == handle_param_selection_sq2 && clipboard.type == CLIP_PARAM_CH2) { | 194 | } else if (input_handler == handle_param_selection_sq2 && clipboard.type == CLIP_PARAM_CH2) { |
@@ -177,7 +196,12 @@ clipboard_paste(void) { | |||
177 | send_notif("PASTED PARAMS"); | 196 | send_notif("PASTED PARAMS"); |
178 | draw_parameters(); | 197 | draw_parameters(); |
179 | } else if (input_handler == handle_param_selection_sq2 && clipboard.type == CLIP_PARAM_CH1) { | 198 | } else if (input_handler == handle_param_selection_sq2 && clipboard.type == CLIP_PARAM_CH1) { |
180 | pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; | 199 | pat_dst->ch2.params[trig_selection_loc].env_volume = pat_src->ch1.params[clipboard.src_trig].env_volume; |
200 | pat_dst->ch2.params[trig_selection_loc].env_time = pat_src->ch1.params[clipboard.src_trig].env_time; | ||
201 | pat_dst->ch2.params[trig_selection_loc].env_direction = pat_src->ch1.params[clipboard.src_trig].env_direction; | ||
202 | pat_dst->ch2.params[trig_selection_loc].duty_cycle = pat_src->ch1.params[clipboard.src_trig].duty_cycle; | ||
203 | pat_dst->ch2.params[trig_selection_loc].prob = pat_src->ch1.params[clipboard.src_trig].prob; | ||
204 | pat_dst->ch2.params[trig_selection_loc].pan = pat_src->ch1.params[clipboard.src_trig].pan; | ||
181 | send_notif("PASTED PARAMS"); | 205 | send_notif("PASTED PARAMS"); |
182 | draw_parameters(); | 206 | draw_parameters(); |
183 | } else if (input_handler == handle_param_selection_wave && clipboard.type == CLIP_PARAM_CH3) { | 207 | } else if (input_handler == handle_param_selection_wave && clipboard.type == CLIP_PARAM_CH3) { |
@@ -198,7 +222,6 @@ clipboard_paste(void) { | |||
198 | case 2: { pat_dst->ch3 = pat_src->ch3; } break; | 222 | case 2: { pat_dst->ch3 = pat_src->ch3; } break; |
199 | case 3: { pat_dst->ch4 = pat_src->ch4; } break; | 223 | case 3: { pat_dst->ch4 = pat_src->ch4; } break; |
200 | } | 224 | } |
201 | send_notif("PASTED NOTES & PARAMS"); | ||
202 | } else { | 225 | } else { |
203 | switch (clipboard.src_chan) { | 226 | switch (clipboard.src_chan) { |
204 | case 0: { | 227 | case 0: { |
@@ -208,26 +231,31 @@ clipboard_paste(void) { | |||
208 | pat_dst->ch1.notes[i] = pat_src->ch1.notes[i]; | 231 | pat_dst->ch1.notes[i] = pat_src->ch1.notes[i]; |
209 | pat_dst->ch1.params[i] = pat_src->ch1.params[i]; | 232 | pat_dst->ch1.params[i] = pat_src->ch1.params[i]; |
210 | } | 233 | } |
211 | send_notif("PASTED NOTES & PARAMS"); | ||
212 | } break; | 234 | } break; |
213 | case 1: { | 235 | case 1: { |
214 | for (size_t i = 0; i < 16; i++) { | 236 | for (size_t i = 0; i < 16; i++) { |
215 | pat_dst->ch2.notes[i] = pat_src->ch1.notes[i]; | 237 | pat_dst->ch2.notes[i] = pat_src->ch1.notes[i]; |
216 | pat_dst->ch2.params[i] = pat_src->ch1.params[i]; | 238 | pat_dst->ch2.params[i].env_volume = pat_src->ch1.params[i].env_volume; |
239 | pat_dst->ch2.params[i].env_time = pat_src->ch1.params[i].env_time; | ||
240 | pat_dst->ch2.params[i].env_direction = pat_src->ch1.params[i].env_direction; | ||
241 | pat_dst->ch2.params[i].duty_cycle = pat_src->ch1.params[i].duty_cycle; | ||
242 | pat_dst->ch2.params[i].prob = pat_src->ch1.params[i].prob; | ||
243 | pat_dst->ch2.params[i].pan = pat_src->ch1.params[i].pan; | ||
217 | } | 244 | } |
218 | send_notif("PASTED NOTES & PARAMS"); | ||
219 | } break; | 245 | } break; |
220 | case 2: { | 246 | case 2: { |
221 | for (size_t i = 0; i < 16; i++) { | 247 | for (size_t i = 0; i < 16; i++) { |
222 | pat_dst->ch3.notes[i] = pat_src->ch1.notes[i]; | 248 | pat_dst->ch3.notes[i] = pat_src->ch1.notes[i]; |
249 | pat_dst->ch3.params[i].prob = pat_src->ch1.params[i].prob; | ||
250 | pat_dst->ch3.params[i].pan = pat_src->ch1.params[i].pan; | ||
223 | } | 251 | } |
224 | send_notif("PASTED NOTES"); | ||
225 | } break; | 252 | } break; |
226 | case 3: { | 253 | case 3: { |
227 | for (size_t i = 0; i < 16; i++) { | 254 | for (size_t i = 0; i < 16; i++) { |
228 | pat_dst->ch4.notes[i] = pat_src->ch1.notes[i]; | 255 | pat_dst->ch4.notes[i] = pat_src->ch1.notes[i]; |
256 | pat_dst->ch4.params[i].prob = pat_src->ch1.params[i].prob; | ||
257 | pat_dst->ch4.params[i].pan = pat_src->ch1.params[i].pan; | ||
229 | } | 258 | } |
230 | send_notif("PASTED NOTES"); | ||
231 | } break; | 259 | } break; |
232 | } | 260 | } |
233 | } break; | 261 | } break; |
@@ -240,27 +268,29 @@ clipboard_paste(void) { | |||
240 | pat_dst->ch1.params[i].env_time = pat_src->ch2.params[i].env_time; | 268 | pat_dst->ch1.params[i].env_time = pat_src->ch2.params[i].env_time; |
241 | pat_dst->ch1.params[i].env_direction = pat_src->ch2.params[i].env_direction; | 269 | pat_dst->ch1.params[i].env_direction = pat_src->ch2.params[i].env_direction; |
242 | pat_dst->ch1.params[i].duty_cycle = pat_src->ch2.params[i].duty_cycle; | 270 | pat_dst->ch1.params[i].duty_cycle = pat_src->ch2.params[i].duty_cycle; |
271 | pat_dst->ch1.params[i].prob = pat_src->ch2.params[i].prob; | ||
272 | pat_dst->ch1.params[i].pan = pat_src->ch2.params[i].pan; | ||
243 | } | 273 | } |
244 | send_notif("PASTED NOTES & PARAMS"); | ||
245 | } break; | 274 | } break; |
246 | case 1: { | 275 | case 1: { |
247 | for (size_t i = 0; i < 16; i++) { | 276 | for (size_t i = 0; i < 16; i++) { |
248 | pat_dst->ch2.notes[i] = pat_src->ch2.notes[i]; | 277 | pat_dst->ch2.notes[i] = pat_src->ch2.notes[i]; |
249 | pat_dst->ch2.params[i] = pat_src->ch2.params[i]; | 278 | pat_dst->ch2.params[i] = pat_src->ch2.params[i]; |
250 | } | 279 | } |
251 | send_notif("PASTED NOTES & PARAMS"); | ||
252 | } break; | 280 | } break; |
253 | case 2: { | 281 | case 2: { |
254 | for (size_t i = 0; i < 16; i++) { | 282 | for (size_t i = 0; i < 16; i++) { |
255 | pat_dst->ch3.notes[i] = pat_src->ch2.notes[i]; | 283 | pat_dst->ch3.notes[i] = pat_src->ch2.notes[i]; |
284 | pat_dst->ch3.params[i].prob = pat_src->ch2.params[i].prob; | ||
285 | pat_dst->ch3.params[i].pan = pat_src->ch2.params[i].pan; | ||
256 | } | 286 | } |
257 | send_notif("PASTED NOTES"); | ||
258 | } break; | 287 | } break; |
259 | case 3: { | 288 | case 3: { |
260 | for (size_t i = 0; i < 16; i++) { | 289 | for (size_t i = 0; i < 16; i++) { |
261 | pat_dst->ch4.notes[i] = pat_src->ch2.notes[i]; | 290 | pat_dst->ch4.notes[i] = pat_src->ch2.notes[i]; |
291 | pat_dst->ch4.params[i].prob = pat_src->ch2.params[i].prob; | ||
292 | pat_dst->ch4.params[i].pan = pat_src->ch2.params[i].pan; | ||
262 | } | 293 | } |
263 | send_notif("PASTED NOTES"); | ||
264 | } break; | 294 | } break; |
265 | } | 295 | } |
266 | } break; | 296 | } break; |
@@ -269,27 +299,29 @@ clipboard_paste(void) { | |||
269 | case 0: { | 299 | case 0: { |
270 | for (size_t i = 0; i < 16; i++) { | 300 | for (size_t i = 0; i < 16; i++) { |
271 | pat_dst->ch1.notes[i] = pat_src->ch3.notes[i]; | 301 | pat_dst->ch1.notes[i] = pat_src->ch3.notes[i]; |
302 | pat_dst->ch1.params[i].prob = pat_src->ch3.params[i].prob; | ||
303 | pat_dst->ch1.params[i].pan = pat_src->ch3.params[i].pan; | ||
272 | } | 304 | } |
273 | send_notif("PASTED NOTES"); | ||
274 | } break; | 305 | } break; |
275 | case 1: { | 306 | case 1: { |
276 | for (size_t i = 0; i < 16; i++) { | 307 | for (size_t i = 0; i < 16; i++) { |
277 | pat_dst->ch2.notes[i] = pat_src->ch3.notes[i]; | 308 | pat_dst->ch2.notes[i] = pat_src->ch3.notes[i]; |
309 | pat_dst->ch2.params[i].prob = pat_src->ch3.params[i].prob; | ||
310 | pat_dst->ch2.params[i].pan = pat_src->ch3.params[i].pan; | ||
278 | } | 311 | } |
279 | send_notif("PASTED NOTES"); | ||
280 | } break; | 312 | } break; |
281 | case 2: { | 313 | case 2: { |
282 | for (size_t i = 0; i < 16; i++) { | 314 | for (size_t i = 0; i < 16; i++) { |
283 | pat_dst->ch3.notes[i] = pat_src->ch3.notes[i]; | 315 | pat_dst->ch3.notes[i] = pat_src->ch3.notes[i]; |
284 | pat_dst->ch3.params[i] = pat_src->ch3.params[i]; | 316 | pat_dst->ch3.params[i] = pat_src->ch3.params[i]; |
285 | } | 317 | } |
286 | send_notif("PASTED NOTES & PARAMS"); | ||
287 | } break; | 318 | } break; |
288 | case 3: { | 319 | case 3: { |
289 | for (size_t i = 0; i < 16; i++) { | 320 | for (size_t i = 0; i < 16; i++) { |
290 | pat_dst->ch4.notes[i] = pat_src->ch3.notes[i]; | 321 | pat_dst->ch4.notes[i] = pat_src->ch3.notes[i]; |
322 | pat_dst->ch4.params[i].prob = pat_src->ch3.params[i].prob; | ||
323 | pat_dst->ch4.params[i].pan = pat_src->ch3.params[i].pan; | ||
291 | } | 324 | } |
292 | send_notif("PASTED NOTES"); | ||
293 | } break; | 325 | } break; |
294 | } | 326 | } |
295 | } break; | 327 | } break; |
@@ -298,32 +330,35 @@ clipboard_paste(void) { | |||
298 | case 0: { | 330 | case 0: { |
299 | for (size_t i = 0; i < 16; i++) { | 331 | for (size_t i = 0; i < 16; i++) { |
300 | pat_dst->ch1.notes[i] = pat_src->ch4.notes[i]; | 332 | pat_dst->ch1.notes[i] = pat_src->ch4.notes[i]; |
333 | pat_dst->ch1.params[i].prob = pat_src->ch4.params[i].prob; | ||
334 | pat_dst->ch1.params[i].pan = pat_src->ch4.params[i].pan; | ||
301 | } | 335 | } |
302 | send_notif("PASTED NOTES"); | ||
303 | } break; | 336 | } break; |
304 | case 1: { | 337 | case 1: { |
305 | for (size_t i = 0; i < 16; i++) { | 338 | for (size_t i = 0; i < 16; i++) { |
306 | pat_dst->ch2.notes[i] = pat_src->ch4.notes[i]; | 339 | pat_dst->ch2.notes[i] = pat_src->ch4.notes[i]; |
340 | pat_dst->ch2.params[i].prob = pat_src->ch4.params[i].prob; | ||
341 | pat_dst->ch2.params[i].pan = pat_src->ch4.params[i].pan; | ||
307 | } | 342 | } |
308 | send_notif("PASTED NOTES"); | ||
309 | } break; | 343 | } break; |
310 | case 2: { | 344 | case 2: { |
311 | for (size_t i = 0; i < 16; i++) { | 345 | for (size_t i = 0; i < 16; i++) { |
312 | pat_dst->ch3.notes[i] = pat_src->ch4.notes[i]; | 346 | pat_dst->ch3.notes[i] = pat_src->ch4.notes[i]; |
347 | pat_dst->ch3.params[i].prob = pat_src->ch4.params[i].prob; | ||
348 | pat_dst->ch3.params[i].pan = pat_src->ch4.params[i].pan; | ||
313 | } | 349 | } |
314 | send_notif("PASTED NOTES"); | ||
315 | } break; | 350 | } break; |
316 | case 3: { | 351 | case 3: { |
317 | for (size_t i = 0; i < 16; i++) { | 352 | for (size_t i = 0; i < 16; i++) { |
318 | pat_dst->ch4.notes[i] = pat_src->ch4.notes[i]; | 353 | pat_dst->ch4.notes[i] = pat_src->ch4.notes[i]; |
319 | pat_dst->ch4.params[i] = pat_src->ch4.params[i]; | 354 | pat_dst->ch4.params[i] = pat_src->ch4.params[i]; |
320 | } | 355 | } |
321 | send_notif("PASTED NOTES & PARAMS"); | ||
322 | } break; | 356 | } break; |
323 | } | 357 | } |
324 | } break; | 358 | } break; |
325 | } | 359 | } |
326 | } | 360 | } |
361 | send_notif("PASTED NOTES & PARAMS"); | ||
327 | draw_channels(); | 362 | draw_channels(); |
328 | draw_triggers(); | 363 | draw_triggers(); |
329 | } else if (input_handler == handle_channel_selection) { | 364 | } else if (input_handler == handle_channel_selection) { |
@@ -344,11 +379,15 @@ clipboard_paste(void) { | |||
344 | ch1_params.env_time = pat_src->ch2.params[clipboard.src_trig].env_time; | 379 | ch1_params.env_time = pat_src->ch2.params[clipboard.src_trig].env_time; |
345 | ch1_params.env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; | 380 | ch1_params.env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; |
346 | ch1_params.duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; | 381 | ch1_params.duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; |
382 | ch1_params.prob = pat_src->ch2.params[clipboard.src_trig].prob; | ||
383 | ch1_params.pan = pat_src->ch2.params[clipboard.src_trig].pan; | ||
347 | for (size_t i = 0; i < 16; i++) { | 384 | for (size_t i = 0; i < 16; i++) { |
348 | pat_dst->ch1.params[i].env_volume = pat_src->ch2.params[clipboard.src_trig].env_volume; | 385 | pat_dst->ch1.params[i].env_volume = pat_src->ch2.params[clipboard.src_trig].env_volume; |
349 | pat_dst->ch1.params[i].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; | 386 | pat_dst->ch1.params[i].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; |
350 | pat_dst->ch1.params[i].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; | 387 | pat_dst->ch1.params[i].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; |
351 | pat_dst->ch1.params[i].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; | 388 | pat_dst->ch1.params[i].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; |
389 | pat_dst->ch1.params[i].prob = pat_src->ch2.params[clipboard.src_trig].prob; | ||
390 | pat_dst->ch1.params[i].pan = pat_src->ch2.params[clipboard.src_trig].pan; | ||
352 | } | 391 | } |
353 | send_notif("PASTED PARAMS"); | 392 | send_notif("PASTED PARAMS"); |
354 | } | 393 | } |
@@ -359,9 +398,19 @@ clipboard_paste(void) { | |||
359 | clipboard.type == CLIP_PARAM_CH1 || | 398 | clipboard.type == CLIP_PARAM_CH1 || |
360 | clipboard.type == CLIP_PARAM_CH2) { | 399 | clipboard.type == CLIP_PARAM_CH2) { |
361 | if (clipboard.src_chan == 0) { | 400 | if (clipboard.src_chan == 0) { |
362 | ch2_params = pat_src->ch1.params[clipboard.src_trig]; | 401 | ch2_params.env_volume = pat_src->ch1.params[clipboard.src_trig].env_volume; |
402 | ch2_params.env_time = pat_src->ch1.params[clipboard.src_trig].env_time; | ||
403 | ch2_params.env_direction = pat_src->ch1.params[clipboard.src_trig].env_direction; | ||
404 | ch2_params.duty_cycle = pat_src->ch1.params[clipboard.src_trig].duty_cycle; | ||
405 | ch2_params.prob = pat_src->ch1.params[clipboard.src_trig].prob; | ||
406 | ch2_params.pan = pat_src->ch1.params[clipboard.src_trig].pan; | ||
363 | for (size_t i = 0; i < 16; i++) { | 407 | for (size_t i = 0; i < 16; i++) { |
364 | pat_dst->ch2.params[i] = pat_src->ch1.params[clipboard.src_trig]; | 408 | pat_dst->ch2.params[i].env_volume = pat_src->ch1.params[clipboard.src_trig].env_volume; |
409 | pat_dst->ch2.params[i].env_time = pat_src->ch1.params[clipboard.src_trig].env_time; | ||
410 | pat_dst->ch2.params[i].env_direction = pat_src->ch1.params[clipboard.src_trig].env_direction; | ||
411 | pat_dst->ch2.params[i].duty_cycle = pat_src->ch1.params[clipboard.src_trig].duty_cycle; | ||
412 | pat_dst->ch2.params[i].prob = pat_src->ch1.params[clipboard.src_trig].prob; | ||
413 | pat_dst->ch2.params[i].pan = pat_src->ch1.params[clipboard.src_trig].pan; | ||
365 | } | 414 | } |
366 | send_notif("PASTED PARAMS"); | 415 | send_notif("PASTED PARAMS"); |
367 | } | 416 | } |
diff --git a/src/drawing.c b/src/drawing.c index 2368627..f18f094 100644 --- a/src/drawing.c +++ b/src/drawing.c | |||
@@ -681,6 +681,16 @@ draw_params_cursor_wave(size_t i, u8 clr) { | |||
681 | y += PARAMS_BOX_H - 7 + PARAMS_BOX_OFFSET_Y; | 681 | y += PARAMS_BOX_H - 7 + PARAMS_BOX_OFFSET_Y; |
682 | txt_drawf_small("vol", x, y, COL_BG); | 682 | txt_drawf_small("vol", x, y, COL_BG); |
683 | } break; | 683 | } break; |
684 | case 7: { | ||
685 | x += 2 + PARAMS_BOX_OFFSET_X * 2; | ||
686 | y += PARAMS_BOX_H - 7 + PARAMS_BOX_OFFSET_Y; | ||
687 | txt_drawf_small("attack", x, y, COL_BG); | ||
688 | } break; | ||
689 | case 8: { | ||
690 | x += 4 + PARAMS_BOX_OFFSET_X * 3; | ||
691 | y += PARAMS_BOX_H - 7 + PARAMS_BOX_OFFSET_Y; | ||
692 | txt_drawf_small("decay", x, y, COL_BG); | ||
693 | } break; | ||
684 | case 9: { | 694 | case 9: { |
685 | x += 8 + PARAMS_BOX_OFFSET_X * 4; | 695 | x += 8 + PARAMS_BOX_OFFSET_X * 4; |
686 | y += PARAMS_BOX_H - 7 + PARAMS_BOX_OFFSET_Y; | 696 | y += PARAMS_BOX_H - 7 + PARAMS_BOX_OFFSET_Y; |
@@ -1012,6 +1022,32 @@ draw_parameters_wave(ChannelWaveParams *params, bool global) { | |||
1012 | } | 1022 | } |
1013 | } | 1023 | } |
1014 | 1024 | ||
1025 | // Attack. | ||
1026 | { | ||
1027 | size_t x = PARAMS_START_X + PARAMS_BOX_OFFSET_X * 2 + 3; | ||
1028 | size_t y = PARAMS_START_Y + PARAMS_BOX_OFFSET_Y + 5; | ||
1029 | if (params->wave_attack == 0) { | ||
1030 | txt_drawf("OFF", x + 3, y, cols[6]); | ||
1031 | } else if (params->wave_attack < 10) { | ||
1032 | txt_drawf("%d", x + 8, y, cols[6], params->wave_attack); | ||
1033 | } else { | ||
1034 | txt_drawf("%d", x + 6, y, cols[6], params->wave_attack); | ||
1035 | } | ||
1036 | } | ||
1037 | |||
1038 | // Decay. | ||
1039 | { | ||
1040 | size_t x = PARAMS_START_X + PARAMS_BOX_OFFSET_X * 3 + 3; | ||
1041 | size_t y = PARAMS_START_Y + PARAMS_BOX_OFFSET_Y + 5; | ||
1042 | if (params->wave_decay == 0) { | ||
1043 | txt_drawf("OFF", x + 3, y, cols[6]); | ||
1044 | } else if (params->wave_decay < 10) { | ||
1045 | txt_drawf("%d", x + 8, y, cols[6], params->wave_decay); | ||
1046 | } else { | ||
1047 | txt_drawf("%d", x + 6, y, cols[6], params->wave_decay); | ||
1048 | } | ||
1049 | } | ||
1050 | |||
1015 | // Labels. | 1051 | // Labels. |
1016 | { | 1052 | { |
1017 | size_t x = PARAMS_START_X; | 1053 | size_t x = PARAMS_START_X; |
@@ -1024,18 +1060,14 @@ draw_parameters_wave(ChannelWaveParams *params, bool global) { | |||
1024 | y += PARAMS_BOX_OFFSET_Y; | 1060 | y += PARAMS_BOX_OFFSET_Y; |
1025 | txt_drawf_small("voice", x + 4 + PARAMS_BOX_OFFSET_X * 0, y + PARAMS_BOX_H - 7, cols[5]); | 1061 | txt_drawf_small("voice", x + 4 + PARAMS_BOX_OFFSET_X * 0, y + PARAMS_BOX_H - 7, cols[5]); |
1026 | txt_drawf_small("vol", x + 8 + PARAMS_BOX_OFFSET_X * 1, y + PARAMS_BOX_H - 7, cols[6]); | 1062 | txt_drawf_small("vol", x + 8 + PARAMS_BOX_OFFSET_X * 1, y + PARAMS_BOX_H - 7, cols[6]); |
1063 | txt_drawf_small("attack", x + 2 + PARAMS_BOX_OFFSET_X * 2, y + PARAMS_BOX_H - 7, cols[7]); | ||
1064 | txt_drawf_small("decay", x + 4 + PARAMS_BOX_OFFSET_X * 3, y + PARAMS_BOX_H - 7, cols[8]); | ||
1027 | txt_drawf_small("pan", x + 8 + PARAMS_BOX_OFFSET_X * 4, y + PARAMS_BOX_H - 7, cols[9]); | 1065 | txt_drawf_small("pan", x + 8 + PARAMS_BOX_OFFSET_X * 4, y + PARAMS_BOX_H - 7, cols[9]); |
1028 | } | 1066 | } |
1029 | |||
1030 | // Empty spacers. | ||
1031 | { | ||
1032 | draw_param_stub(7, COL_OFF); | ||
1033 | draw_param_stub(8, COL_OFF); | ||
1034 | } | ||
1035 | } | 1067 | } |
1036 | 1068 | ||
1037 | void | 1069 | void |
1038 | draw_parameters_square(ChannelSquareParams *params, bool sweep, bool global) { | 1070 | draw_parameters_square1(ChannelSquare1Params *params, bool global) { |
1039 | u8 cols[10] = { | 1071 | u8 cols[10] = { |
1040 | COL_FG, COL_FG, COL_FG, COL_FG, COL_FG, | 1072 | COL_FG, COL_FG, COL_FG, COL_FG, COL_FG, |
1041 | COL_FG, COL_FG, COL_FG, COL_FG, COL_FG, | 1073 | COL_FG, COL_FG, COL_FG, COL_FG, COL_FG, |
@@ -1044,12 +1076,8 @@ draw_parameters_square(ChannelSquareParams *params, bool sweep, bool global) { | |||
1044 | // Adjust colors for global trigger parameters. | 1076 | // Adjust colors for global trigger parameters. |
1045 | if (global && input_handler == handle_channel_selection) { | 1077 | if (global && input_handler == handle_channel_selection) { |
1046 | for (size_t i = 0; i < 16; i++) { | 1078 | for (size_t i = 0; i < 16; i++) { |
1047 | ChannelSquareParams *trig_params; | 1079 | ChannelSquare1Params *trig_params; |
1048 | if (sweep) { | 1080 | trig_params = &patterns[pattern_selection_loc].ch1.params[i]; |
1049 | trig_params = &patterns[pattern_selection_loc].ch1.params[i]; | ||
1050 | } else { | ||
1051 | trig_params = &patterns[pattern_selection_loc].ch2.params[i]; | ||
1052 | } | ||
1053 | if (params->duty_cycle != trig_params->duty_cycle) { | 1081 | if (params->duty_cycle != trig_params->duty_cycle) { |
1054 | cols[0] = COL_OFF; | 1082 | cols[0] = COL_OFF; |
1055 | } | 1083 | } |
@@ -1168,7 +1196,7 @@ draw_parameters_square(ChannelSquareParams *params, bool sweep, bool global) { | |||
1168 | draw_panning(params->pan, cols[9]); | 1196 | draw_panning(params->pan, cols[9]); |
1169 | 1197 | ||
1170 | // Sweep. | 1198 | // Sweep. |
1171 | if (sweep) { | 1199 | { |
1172 | size_t x = PARAMS_START_X; | 1200 | size_t x = PARAMS_START_X; |
1173 | size_t y = PARAMS_START_Y + PARAMS_BOX_OFFSET_Y; | 1201 | size_t y = PARAMS_START_Y + PARAMS_BOX_OFFSET_Y; |
1174 | 1202 | ||
@@ -1229,21 +1257,156 @@ draw_parameters_square(ChannelSquareParams *params, bool sweep, bool global) { | |||
1229 | txt_drawf_small("dir", x + 8 + PARAMS_BOX_OFFSET_X * 3, y + PARAMS_BOX_H - 7, cols[3]); | 1257 | txt_drawf_small("dir", x + 8 + PARAMS_BOX_OFFSET_X * 3, y + PARAMS_BOX_H - 7, cols[3]); |
1230 | txt_drawf_small("prob", x + 6 + PARAMS_BOX_OFFSET_X * 4, y + PARAMS_BOX_H - 7, cols[4]); | 1258 | txt_drawf_small("prob", x + 6 + PARAMS_BOX_OFFSET_X * 4, y + PARAMS_BOX_H - 7, cols[4]); |
1231 | y += PARAMS_BOX_OFFSET_Y; | 1259 | y += PARAMS_BOX_OFFSET_Y; |
1232 | if (sweep) { | 1260 | txt_drawf_small("sweep", x + 4 + PARAMS_BOX_OFFSET_X * 0, y + PARAMS_BOX_H - 7, cols[5]); |
1233 | txt_drawf_small("sweep", x + 4 + PARAMS_BOX_OFFSET_X * 0, y + PARAMS_BOX_H - 7, cols[5]); | 1261 | txt_drawf_small("time", x + 6 + PARAMS_BOX_OFFSET_X * 1, y + PARAMS_BOX_H - 7, cols[6]); |
1234 | txt_drawf_small("time", x + 6 + PARAMS_BOX_OFFSET_X * 1, y + PARAMS_BOX_H - 7, cols[6]); | 1262 | txt_drawf_small("dir", x + 8 + PARAMS_BOX_OFFSET_X * 2, y + PARAMS_BOX_H - 7, cols[7]); |
1235 | txt_drawf_small("dir", x + 8 + PARAMS_BOX_OFFSET_X * 2, y + PARAMS_BOX_H - 7, cols[7]); | ||
1236 | } | ||
1237 | txt_drawf_small("pan", x + 8 + PARAMS_BOX_OFFSET_X * 4, y + PARAMS_BOX_H - 7, cols[9]); | 1263 | txt_drawf_small("pan", x + 8 + PARAMS_BOX_OFFSET_X * 4, y + PARAMS_BOX_H - 7, cols[9]); |
1238 | } | 1264 | } |
1239 | 1265 | ||
1240 | // Empty spacers. | 1266 | // Empty spacers. |
1241 | { | 1267 | { |
1242 | if (!sweep) { | 1268 | draw_param_stub(8, COL_OFF); |
1243 | draw_param_stub(5, COL_OFF); | 1269 | } |
1244 | draw_param_stub(6, COL_OFF); | 1270 | } |
1245 | draw_param_stub(7, COL_OFF); | 1271 | |
1272 | void | ||
1273 | draw_parameters_square2(ChannelSquare2Params *params, bool global) { | ||
1274 | u8 cols[10] = { | ||
1275 | COL_FG, COL_FG, COL_FG, COL_FG, COL_FG, | ||
1276 | COL_FG, COL_FG, COL_FG, COL_FG, COL_FG, | ||
1277 | }; | ||
1278 | |||
1279 | // Adjust colors for global trigger parameters. | ||
1280 | if (global && input_handler == handle_channel_selection) { | ||
1281 | for (size_t i = 0; i < 16; i++) { | ||
1282 | ChannelSquare2Params *trig_params; | ||
1283 | trig_params = &patterns[pattern_selection_loc].ch2.params[i]; | ||
1284 | if (params->duty_cycle != trig_params->duty_cycle) { | ||
1285 | cols[0] = COL_OFF; | ||
1286 | } | ||
1287 | if (params->env_volume != trig_params->env_volume) { | ||
1288 | cols[1] = COL_OFF; | ||
1289 | } | ||
1290 | if (params->env_time != trig_params->env_time) { | ||
1291 | cols[2] = COL_OFF; | ||
1292 | } | ||
1293 | if (params->env_direction != trig_params->env_direction) { | ||
1294 | cols[3] = COL_OFF; | ||
1295 | } | ||
1296 | if (params->env_direction != trig_params->env_direction) { | ||
1297 | cols[3] = COL_OFF; | ||
1298 | } | ||
1299 | if (params->prob != trig_params->prob) { | ||
1300 | cols[4] = COL_OFF; | ||
1301 | } | ||
1302 | if (params->pan != trig_params->pan) { | ||
1303 | cols[9] = COL_OFF; | ||
1304 | } | ||
1246 | } | 1305 | } |
1306 | } | ||
1307 | |||
1308 | // Duty cycle / shape. | ||
1309 | { | ||
1310 | size_t x = PARAMS_START_X + 3; | ||
1311 | size_t y = PARAMS_START_Y + 1; | ||
1312 | |||
1313 | size_t x0 = x + 2; | ||
1314 | size_t x1 = x0; | ||
1315 | size_t x2 = x0; | ||
1316 | size_t x3 = x0; | ||
1317 | size_t x4 = x0; | ||
1318 | size_t x5 = x0; | ||
1319 | size_t y0 = y + 14; | ||
1320 | size_t y1 = y + 2; | ||
1321 | |||
1322 | switch (params->duty_cycle) { | ||
1323 | case 0: { | ||
1324 | x1 += 4; | ||
1325 | x2 += 6; | ||
1326 | x3 += 13; | ||
1327 | x4 += 15; | ||
1328 | x5 += 20; | ||
1329 | } break; | ||
1330 | case 1: { | ||
1331 | x1 += 4; | ||
1332 | x2 += 7; | ||
1333 | x3 += 13; | ||
1334 | x4 += 16; | ||
1335 | x5 += 20; | ||
1336 | } break; | ||
1337 | case 2: { | ||
1338 | x1 += 3; | ||
1339 | x2 += 8; | ||
1340 | x3 += 12; | ||
1341 | x4 += 17; | ||
1342 | x5 += 20; | ||
1343 | } break; | ||
1344 | case 3: { | ||
1345 | x1 += 2; | ||
1346 | x2 += 9; | ||
1347 | x3 += 11; | ||
1348 | x4 += 18; | ||
1349 | x5 += 20; | ||
1350 | } break; | ||
1351 | } | ||
1352 | u8 col_shape = cols[0] != COL_OFF ? COL_ACC_1 : COL_OFF; | ||
1353 | draw_line(x0, y0, x1, y0, col_shape); | ||
1354 | draw_line(x1, y1, x1, y0, col_shape); | ||
1355 | draw_line(x1, y1, x2, y1, col_shape); | ||
1356 | draw_line(x2, y1, x2, y0, col_shape); | ||
1357 | draw_line(x2, y0, x3, y0, col_shape); | ||
1358 | draw_line(x3, y1, x3, y0, col_shape); | ||
1359 | draw_line(x3, y1, x4, y1, col_shape); | ||
1360 | draw_line(x4, y1, x4, y0, col_shape); | ||
1361 | draw_line(x4, y0, x5, y0, col_shape); | ||
1362 | } | ||
1363 | |||
1364 | // Envelope. | ||
1365 | { | ||
1366 | size_t x = PARAMS_START_X + PARAMS_BOX_OFFSET_X * 1 + 1; | ||
1367 | size_t y = PARAMS_START_Y + 1; | ||
1368 | size_t x0 = x; | ||
1369 | size_t y0 = y + 15 - params->env_volume; | ||
1370 | size_t x1 = x + (3 * PARAMS_BOX_OFFSET_X) * params->env_time / 8 + 7; | ||
1371 | size_t y1 = params->env_direction == 0 ? y + 15 : y; | ||
1372 | size_t x2 = x + PARAMS_BOX_OFFSET_X * 3 - 5; | ||
1373 | size_t y2 = y1; | ||
1374 | |||
1375 | // Env. | ||
1376 | u8 col_env = cols[1] != COL_OFF && cols[2] != COL_OFF && cols[3] != COL_OFF | ||
1377 | ? COL_ACC_2 : COL_OFF; | ||
1378 | if (params->env_time == 0) { | ||
1379 | draw_line(x0, y0, x2, y0, col_env); | ||
1380 | } else { | ||
1381 | draw_line(x0, y0, x1, y1, col_env); | ||
1382 | draw_line(x1, y1, x2, y2, col_env); | ||
1383 | } | ||
1384 | } | ||
1385 | |||
1386 | // Trig probability. | ||
1387 | draw_prob(params->prob, cols[4]); | ||
1388 | |||
1389 | // Trig pannning. | ||
1390 | draw_panning(params->pan, cols[9]); | ||
1391 | |||
1392 | // Labels. | ||
1393 | { | ||
1394 | size_t x = PARAMS_START_X; | ||
1395 | size_t y = PARAMS_START_Y; | ||
1396 | txt_drawf_small("shape", x + 4 + PARAMS_BOX_OFFSET_X * 0, y + PARAMS_BOX_H - 7, cols[0]); | ||
1397 | txt_drawf_small("vol", x + 8 + PARAMS_BOX_OFFSET_X * 1, y + PARAMS_BOX_H - 7, cols[1]); | ||
1398 | txt_drawf_small("time", x + 6 + PARAMS_BOX_OFFSET_X * 2, y + PARAMS_BOX_H - 7, cols[2]); | ||
1399 | txt_drawf_small("dir", x + 8 + PARAMS_BOX_OFFSET_X * 3, y + PARAMS_BOX_H - 7, cols[3]); | ||
1400 | txt_drawf_small("prob", x + 6 + PARAMS_BOX_OFFSET_X * 4, y + PARAMS_BOX_H - 7, cols[4]); | ||
1401 | y += PARAMS_BOX_OFFSET_Y; | ||
1402 | txt_drawf_small("pan", x + 8 + PARAMS_BOX_OFFSET_X * 4, y + PARAMS_BOX_H - 7, cols[9]); | ||
1403 | } | ||
1404 | |||
1405 | // Empty spacers. | ||
1406 | { | ||
1407 | draw_param_stub(5, COL_OFF); | ||
1408 | draw_param_stub(6, COL_OFF); | ||
1409 | draw_param_stub(7, COL_OFF); | ||
1247 | draw_param_stub(8, COL_OFF); | 1410 | draw_param_stub(8, COL_OFF); |
1248 | } | 1411 | } |
1249 | } | 1412 | } |
@@ -1358,15 +1521,15 @@ draw_parameters(void) { | |||
1358 | input_handler == handle_param_selection_noise) { | 1521 | input_handler == handle_param_selection_noise) { |
1359 | if (!pat->empty) { | 1522 | if (!pat->empty) { |
1360 | switch (channel_selection_loc) { | 1523 | switch (channel_selection_loc) { |
1361 | case 0: { draw_parameters_square(&pat->ch1.params[trig_selection_loc], true, false); } break; | 1524 | case 0: { draw_parameters_square1(&pat->ch1.params[trig_selection_loc], false); } break; |
1362 | case 1: { draw_parameters_square(&pat->ch2.params[trig_selection_loc], false, false); } break; | 1525 | case 1: { draw_parameters_square2(&pat->ch2.params[trig_selection_loc], false); } break; |
1363 | case 2: { draw_parameters_wave(&pat->ch3.params[trig_selection_loc], false); } break; | 1526 | case 2: { draw_parameters_wave(&pat->ch3.params[trig_selection_loc], false); } break; |
1364 | case 3: { draw_parameters_noise(&pat->ch4.params[trig_selection_loc], false); } break; | 1527 | case 3: { draw_parameters_noise(&pat->ch4.params[trig_selection_loc], false); } break; |
1365 | } | 1528 | } |
1366 | } else { | 1529 | } else { |
1367 | switch (channel_selection_loc) { | 1530 | switch (channel_selection_loc) { |
1368 | case 0: { draw_parameters_square(&default_ch1.params, true, false); } break; | 1531 | case 0: { draw_parameters_square1(&default_ch1.params, false); } break; |
1369 | case 1: { draw_parameters_square(&default_ch2.params, false, false); } break; | 1532 | case 1: { draw_parameters_square2(&default_ch2.params, false); } break; |
1370 | case 2: { draw_parameters_wave(&default_ch3.params, true); } break; | 1533 | case 2: { draw_parameters_wave(&default_ch3.params, true); } break; |
1371 | case 3: { draw_parameters_noise(&default_ch4.params, true); } break; | 1534 | case 3: { draw_parameters_noise(&default_ch4.params, true); } break; |
1372 | } | 1535 | } |
@@ -1379,8 +1542,8 @@ draw_parameters(void) { | |||
1379 | input_handler == handle_param_selection_ch3 || | 1542 | input_handler == handle_param_selection_ch3 || |
1380 | input_handler == handle_param_selection_ch4) { | 1543 | input_handler == handle_param_selection_ch4) { |
1381 | switch (channel_selection_loc) { | 1544 | switch (channel_selection_loc) { |
1382 | case 0: { draw_parameters_square(&ch1_params, true, true); } break; | 1545 | case 0: { draw_parameters_square1(&ch1_params, true); } break; |
1383 | case 1: { draw_parameters_square(&ch2_params, false, true); } break; | 1546 | case 1: { draw_parameters_square2(&ch2_params, true); } break; |
1384 | case 2: { draw_parameters_wave(&ch3_params, true); } break; | 1547 | case 2: { draw_parameters_wave(&ch3_params, true); } break; |
1385 | case 3: { draw_parameters_noise(&ch4_params, true); } break; | 1548 | case 3: { draw_parameters_noise(&ch4_params, true); } break; |
1386 | } | 1549 | } |
@@ -1640,7 +1803,7 @@ draw_notif_bar() { | |||
1640 | Pattern *pat = &patterns[pattern_selection_loc]; | 1803 | Pattern *pat = &patterns[pattern_selection_loc]; |
1641 | if (input_handler == handle_param_selection_sq1 | 1804 | if (input_handler == handle_param_selection_sq1 |
1642 | || input_handler == handle_param_selection_ch1) { | 1805 | || input_handler == handle_param_selection_ch1) { |
1643 | ChannelSquareParams *params; | 1806 | ChannelSquare1Params *params; |
1644 | if (input_handler == handle_param_selection_sq1) { | 1807 | if (input_handler == handle_param_selection_sq1) { |
1645 | params = &pat->ch1.params[trig_selection_loc]; | 1808 | params = &pat->ch1.params[trig_selection_loc]; |
1646 | } else { | 1809 | } else { |
@@ -1704,7 +1867,7 @@ draw_notif_bar() { | |||
1704 | 1867 | ||
1705 | if (input_handler == handle_param_selection_sq2 | 1868 | if (input_handler == handle_param_selection_sq2 |
1706 | || input_handler == handle_param_selection_ch2) { | 1869 | || input_handler == handle_param_selection_ch2) { |
1707 | ChannelSquareParams *params; | 1870 | ChannelSquare2Params *params; |
1708 | if (input_handler == handle_param_selection_sq2) { | 1871 | if (input_handler == handle_param_selection_sq2) { |
1709 | params = &pat->ch2.params[trig_selection_loc]; | 1872 | params = &pat->ch2.params[trig_selection_loc]; |
1710 | } else { | 1873 | } else { |
@@ -16,6 +16,7 @@ WITH REGARD TO THIS SOFTWARE. | |||
16 | // + Look back again at the emulator issues... (I give up) | 16 | // + Look back again at the emulator issues... (I give up) |
17 | // + Sync via MIDI with the Analogue cables. | 17 | // + Sync via MIDI with the Analogue cables. |
18 | // + Fix bank switching behaviour (bug) | 18 | // + Fix bank switching behaviour (bug) |
19 | // + Fix bug: Clipboard doesn't copy probability/pan? maybe others? | ||
19 | // + Add more sync options | 20 | // + Add more sync options |
20 | // + When switching sync, play status acts wonky (bug) | 21 | // + When switching sync, play status acts wonky (bug) |
21 | // + Channel params should show if there are some already on all triggers and | 22 | // + Channel params should show if there are some already on all triggers and |
@@ -165,6 +166,20 @@ render_settings(void) { | |||
165 | 166 | ||
166 | void | 167 | void |
167 | render(void) { | 168 | render(void) { |
169 | // NOTE: Debug key input | ||
170 | // PROF(screen_fill(COL_BG), clear_cycles); | ||
171 | // txt_printf("UP: %d\n", ctrl.key_up); | ||
172 | // txt_printf("DOWN: %d\n", ctrl.key_down); | ||
173 | // txt_printf("LEFT: %d\n", ctrl.key_left); | ||
174 | // txt_printf("RIGHT: %d\n", ctrl.key_right); | ||
175 | // txt_printf("A: %d\n", ctrl.key_a); | ||
176 | // txt_printf("B: %d\n", ctrl.key_b); | ||
177 | // txt_printf("L: %d\n", ctrl.key_l); | ||
178 | // txt_printf("R: %d\n", ctrl.key_r); | ||
179 | // txt_printf("SEL: %d\n", ctrl.key_select); | ||
180 | // txt_printf("START: %d\n", ctrl.key_start); | ||
181 | // txt_render(); | ||
182 | // txt_clear(); | ||
168 | if (clear_screen) { | 183 | if (clear_screen) { |
169 | PROF(screen_fill(COL_BG), clear_cycles); | 184 | PROF(screen_fill(COL_BG), clear_cycles); |
170 | clear_screen = false; | 185 | clear_screen = false; |
diff --git a/src/patterns.c b/src/patterns.c index a1f8f24..8dd0f5c 100644 --- a/src/patterns.c +++ b/src/patterns.c | |||
@@ -7,7 +7,7 @@ typedef struct TriggerNote { | |||
7 | Note note; | 7 | Note note; |
8 | } TriggerNote; | 8 | } TriggerNote; |
9 | 9 | ||
10 | typedef struct ChannelSquareParams { | 10 | typedef struct ChannelSquare1Params { |
11 | u8 env_volume; | 11 | u8 env_volume; |
12 | u8 env_time; | 12 | u8 env_time; |
13 | u8 env_direction; | 13 | u8 env_direction; |
@@ -17,7 +17,16 @@ typedef struct ChannelSquareParams { | |||
17 | u8 sweep_direction; | 17 | u8 sweep_direction; |
18 | u8 prob; | 18 | u8 prob; |
19 | s8 pan; | 19 | s8 pan; |
20 | } ChannelSquareParams; | 20 | } ChannelSquare1Params; |
21 | |||
22 | typedef struct ChannelSquare2Params { | ||
23 | u8 env_volume; | ||
24 | u8 env_time; | ||
25 | u8 env_direction; | ||
26 | u8 duty_cycle; | ||
27 | u8 prob; | ||
28 | s8 pan; | ||
29 | } ChannelSquare2Params; | ||
21 | 30 | ||
22 | typedef struct ChannelWaveParams { | 31 | typedef struct ChannelWaveParams { |
23 | u8 wave_volume; | 32 | u8 wave_volume; |
@@ -26,6 +35,8 @@ typedef struct ChannelWaveParams { | |||
26 | u8 type_a; | 35 | u8 type_a; |
27 | u8 shape_b; | 36 | u8 shape_b; |
28 | u8 type_b; | 37 | u8 type_b; |
38 | u8 wave_attack; | ||
39 | u8 wave_decay; | ||
29 | u8 prob; | 40 | u8 prob; |
30 | s8 pan; | 41 | s8 pan; |
31 | } ChannelWaveParams; | 42 | } ChannelWaveParams; |
@@ -39,11 +50,17 @@ typedef struct ChannelNoiseParams { | |||
39 | s8 pan; | 50 | s8 pan; |
40 | } ChannelNoiseParams; | 51 | } ChannelNoiseParams; |
41 | 52 | ||
42 | typedef struct ChannelSquare { | 53 | typedef struct ChannelSquare1 { |
43 | bool active; | 54 | bool active; |
44 | TriggerNote notes[16]; | 55 | TriggerNote notes[16]; |
45 | ChannelSquareParams params[16]; | 56 | ChannelSquare1Params params[16]; |
46 | } ChannelSquare; | 57 | } ChannelSquare1; |
58 | |||
59 | typedef struct ChannelSquare2 { | ||
60 | bool active; | ||
61 | TriggerNote notes[16]; | ||
62 | ChannelSquare2Params params[16]; | ||
63 | } ChannelSquare2; | ||
47 | 64 | ||
48 | typedef struct ChannelWave { | 65 | typedef struct ChannelWave { |
49 | bool active; | 66 | bool active; |
@@ -58,8 +75,8 @@ typedef struct ChannelNoise { | |||
58 | } ChannelNoise; | 75 | } ChannelNoise; |
59 | 76 | ||
60 | typedef struct Pattern { | 77 | typedef struct Pattern { |
61 | ChannelSquare ch1; | 78 | ChannelSquare1 ch1; |
62 | ChannelSquare ch2; | 79 | ChannelSquare2 ch2; |
63 | ChannelWave ch3; | 80 | ChannelWave ch3; |
64 | ChannelNoise ch4; | 81 | ChannelNoise ch4; |
65 | int bpm; | 82 | int bpm; |
@@ -71,7 +88,7 @@ typedef struct Pattern { | |||
71 | // Defaults. | 88 | // Defaults. |
72 | // | 89 | // |
73 | 90 | ||
74 | const ChannelSquare default_ch1 = { | 91 | const ChannelSquare1 default_ch1 = { |
75 | .notes = { | 92 | .notes = { |
76 | {true, NOTE_C_4}, | 93 | {true, NOTE_C_4}, |
77 | {true, NOTE_D_SHARP_4}, | 94 | {true, NOTE_D_SHARP_4}, |
@@ -111,7 +128,7 @@ const ChannelSquare default_ch1 = { | |||
111 | .active = true, | 128 | .active = true, |
112 | }; | 129 | }; |
113 | 130 | ||
114 | const ChannelSquare default_ch2 = { | 131 | const ChannelSquare2 default_ch2 = { |
115 | .notes = { | 132 | .notes = { |
116 | {true, NOTE_C_3}, | 133 | {true, NOTE_C_3}, |
117 | {true, NOTE_C_3}, | 134 | {true, NOTE_C_3}, |
@@ -131,22 +148,22 @@ const ChannelSquare default_ch2 = { | |||
131 | {true, NOTE_C_3}, | 148 | {true, NOTE_C_3}, |
132 | }, | 149 | }, |
133 | .params = { | 150 | .params = { |
134 | {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, | 151 | {8, 4, 0, 2, PROB_100, 0}, |
135 | {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, | 152 | {8, 4, 0, 2, PROB_100, 0}, |
136 | {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, | 153 | {8, 4, 0, 2, PROB_100, 0}, |
137 | {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, | 154 | {8, 4, 0, 2, PROB_100, 0}, |
138 | {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, | 155 | {8, 4, 0, 2, PROB_100, 0}, |
139 | {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, | 156 | {8, 4, 0, 2, PROB_100, 0}, |
140 | {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, | 157 | {8, 4, 0, 2, PROB_100, 0}, |
141 | {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, | 158 | {8, 4, 0, 2, PROB_100, 0}, |
142 | {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, | 159 | {8, 4, 0, 2, PROB_100, 0}, |
143 | {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, | 160 | {8, 4, 0, 2, PROB_100, 0}, |
144 | {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, | 161 | {8, 4, 0, 2, PROB_100, 0}, |
145 | {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, | 162 | {8, 4, 0, 2, PROB_100, 0}, |
146 | {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, | 163 | {8, 4, 0, 2, PROB_100, 0}, |
147 | {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, | 164 | {8, 4, 0, 2, PROB_100, 0}, |
148 | {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, | 165 | {8, 4, 0, 2, PROB_100, 0}, |
149 | {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, | 166 | {8, 4, 0, 2, PROB_100, 0}, |
150 | }, | 167 | }, |
151 | .active = true, | 168 | .active = true, |
152 | }; | 169 | }; |
@@ -171,22 +188,22 @@ const ChannelWave default_ch3 = { | |||
171 | {true, NOTE_G_5}, | 188 | {true, NOTE_G_5}, |
172 | }, | 189 | }, |
173 | .params = { | 190 | .params = { |
174 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, | 191 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, |
175 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, | 192 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, |
176 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, | 193 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, |
177 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, | 194 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, |
178 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, | 195 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, |
179 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, | 196 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, |
180 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, | 197 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, |
181 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, | 198 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, |
182 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, | 199 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, |
183 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, | 200 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, |
184 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, | 201 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, |
185 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, | 202 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, |
186 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, | 203 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, |
187 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, | 204 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, |
188 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, | 205 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, |
189 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, | 206 | {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, |
190 | }, | 207 | }, |
191 | .active = true, | 208 | .active = true, |
192 | }; | 209 | }; |
@@ -244,7 +261,7 @@ static Pattern patterns[8] = { | |||
244 | {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0, true}, | 261 | {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0, true}, |
245 | }; | 262 | }; |
246 | 263 | ||
247 | static ChannelSquareParams ch1_params = {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}; | 264 | static ChannelSquare1Params ch1_params = {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}; |
248 | static ChannelSquareParams ch2_params = {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}; | 265 | static ChannelSquare2Params ch2_params = {8, 4, 0, 2, PROB_100, 0}; |
249 | static ChannelWaveParams ch3_params = {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}; | 266 | static ChannelWaveParams ch3_params = {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}; |
250 | static ChannelNoiseParams ch4_params = {0xF, 0x2, 0, 0, PROB_100, 0}; | 267 | static ChannelNoiseParams ch4_params = {0xF, 0x2, 0, 0, PROB_100, 0}; |
diff --git a/src/sequencer.c b/src/sequencer.c index 01b8e95..8863d14 100644 --- a/src/sequencer.c +++ b/src/sequencer.c | |||
@@ -160,7 +160,7 @@ play_step(void) { | |||
160 | bool ch1_active = settings.global_mute ? !settings.mutes[0] : pat->ch1.active; | 160 | bool ch1_active = settings.global_mute ? !settings.mutes[0] : pat->ch1.active; |
161 | if (ch1_active && !pat->empty) { | 161 | if (ch1_active && !pat->empty) { |
162 | TriggerNote *trig = &pat->ch1.notes[step_counter]; | 162 | TriggerNote *trig = &pat->ch1.notes[step_counter]; |
163 | ChannelSquareParams *params = &pat->ch1.params[step_counter]; | 163 | ChannelSquare1Params *params = &pat->ch1.params[step_counter]; |
164 | if (trig->active && should_play(params->prob)) { | 164 | if (trig->active && should_play(params->prob)) { |
165 | if (params->sweep_time == 0) { | 165 | if (params->sweep_time == 0) { |
166 | SOUND_SQUARE1_SWEEP = SOUND_SWEEP_DIR(1); | 166 | SOUND_SQUARE1_SWEEP = SOUND_SWEEP_DIR(1); |
@@ -204,7 +204,7 @@ play_step(void) { | |||
204 | bool ch2_active = settings.global_mute ? !settings.mutes[1] : pat->ch2.active; | 204 | bool ch2_active = settings.global_mute ? !settings.mutes[1] : pat->ch2.active; |
205 | if (ch2_active && !pat->empty) { | 205 | if (ch2_active && !pat->empty) { |
206 | TriggerNote *trig = &pat->ch2.notes[step_counter]; | 206 | TriggerNote *trig = &pat->ch2.notes[step_counter]; |
207 | ChannelSquareParams *params = &pat->ch2.params[step_counter]; | 207 | ChannelSquare2Params *params = &pat->ch2.params[step_counter]; |
208 | if (trig->active && should_play(params->prob)) { | 208 | if (trig->active && should_play(params->prob)) { |
209 | SOUND_SQUARE2_CTRL = SOUND_SQUARE_ENV_VOL(params->env_volume) | 209 | SOUND_SQUARE2_CTRL = SOUND_SQUARE_ENV_VOL(params->env_volume) |
210 | | SOUND_SQUARE_ENV_TIME(params->env_time) | 210 | | SOUND_SQUARE_ENV_TIME(params->env_time) |
@@ -252,6 +252,8 @@ play_step(void) { | |||
252 | } break; | 252 | } break; |
253 | } | 253 | } |
254 | wave_env_ticks = 0; | 254 | wave_env_ticks = 0; |
255 | wave_env_attack = params->wave_attack; | ||
256 | wave_env_decay = params->wave_decay; | ||
255 | SOUND_WAVE_MODE |= SOUND_WAVE_ENABLE; | 257 | SOUND_WAVE_MODE |= SOUND_WAVE_ENABLE; |
256 | 258 | ||
257 | SOUND_WAVE_FREQ = SOUND_FREQ_RESET | 259 | SOUND_WAVE_FREQ = SOUND_FREQ_RESET |
@@ -1075,7 +1077,7 @@ handle_pattern_selection(void) { | |||
1075 | } | 1077 | } |
1076 | 1078 | ||
1077 | bool | 1079 | bool |
1078 | set_param_selection_sq1(ChannelSquareParams *params, InputHandler return_handler) { | 1080 | set_param_selection_sq1(ChannelSquare1Params *params, InputHandler return_handler) { |
1079 | // Go back to trigger selection. | 1081 | // Go back to trigger selection. |
1080 | if (key_released(KEY_A)) { | 1082 | if (key_released(KEY_A)) { |
1081 | input_handler = return_handler; | 1083 | input_handler = return_handler; |
@@ -1159,7 +1161,7 @@ set_param_selection_sq1(ChannelSquareParams *params, InputHandler return_handler | |||
1159 | } | 1161 | } |
1160 | 1162 | ||
1161 | bool | 1163 | bool |
1162 | set_param_selection_sq2(ChannelSquareParams *params, InputHandler return_handler) { | 1164 | set_param_selection_sq2(ChannelSquare2Params *params, InputHandler return_handler) { |
1163 | // Go back to trigger selection. | 1165 | // Go back to trigger selection. |
1164 | if (key_released(KEY_A)) { | 1166 | if (key_released(KEY_A)) { |
1165 | input_handler = return_handler; | 1167 | input_handler = return_handler; |
@@ -1245,11 +1247,9 @@ set_param_selection_wave(ChannelWaveParams *params, InputHandler return_handler) | |||
1245 | if (key_retrig(KEY_RIGHT)) { | 1247 | if (key_retrig(KEY_RIGHT)) { |
1246 | if (param_selection_loc == 4) { | 1248 | if (param_selection_loc == 4) { |
1247 | param_selection_loc = 0; | 1249 | param_selection_loc = 0; |
1248 | } else if (param_selection_loc == 6) { | ||
1249 | param_selection_loc = 9; | ||
1250 | } else if (param_selection_loc == 9) { | 1250 | } else if (param_selection_loc == 9) { |
1251 | param_selection_loc = 5; | 1251 | param_selection_loc = 5; |
1252 | } else if (param_selection_loc < 6) { | 1252 | } else { |
1253 | param_selection_loc++; | 1253 | param_selection_loc++; |
1254 | } | 1254 | } |
1255 | } else { | 1255 | } else { |
@@ -1257,9 +1257,7 @@ set_param_selection_wave(ChannelWaveParams *params, InputHandler return_handler) | |||
1257 | param_selection_loc = 4; | 1257 | param_selection_loc = 4; |
1258 | } else if (param_selection_loc == 5) { | 1258 | } else if (param_selection_loc == 5) { |
1259 | param_selection_loc = 9; | 1259 | param_selection_loc = 9; |
1260 | } else if (param_selection_loc == 9) { | 1260 | } else { |
1261 | param_selection_loc = 6; | ||
1262 | } else if (param_selection_loc > 0) { | ||
1263 | param_selection_loc--; | 1261 | param_selection_loc--; |
1264 | } | 1262 | } |
1265 | } | 1263 | } |
@@ -1268,13 +1266,9 @@ set_param_selection_wave(ChannelWaveParams *params, InputHandler return_handler) | |||
1268 | } | 1266 | } |
1269 | 1267 | ||
1270 | if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) { | 1268 | if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) { |
1271 | if (param_selection_loc == 4) { | 1269 | if (param_selection_loc < 5) { |
1272 | param_selection_loc = 9; | ||
1273 | } else if (param_selection_loc == 9) { | ||
1274 | param_selection_loc = 4; | ||
1275 | } else if (param_selection_loc < 2) { | ||
1276 | param_selection_loc += 5; | 1270 | param_selection_loc += 5; |
1277 | } else if (param_selection_loc > 4) { | 1271 | } else if (param_selection_loc >= 5) { |
1278 | param_selection_loc -= 5; | 1272 | param_selection_loc -= 5; |
1279 | } | 1273 | } |
1280 | redraw_params = true; | 1274 | redraw_params = true; |
@@ -1297,6 +1291,8 @@ set_param_selection_wave(ChannelWaveParams *params, InputHandler return_handler) | |||
1297 | case 4: { params->prob = CLAMP(params->prob + inc * -1, 0, PROB_NUM - 1); } break; | 1291 | case 4: { params->prob = CLAMP(params->prob + inc * -1, 0, PROB_NUM - 1); } break; |
1298 | case 5: { params->wave_mode = CLAMP(params->wave_mode + inc, 0, 2); } break; | 1292 | case 5: { params->wave_mode = CLAMP(params->wave_mode + inc, 0, 2); } break; |
1299 | case 6: { params->wave_volume = CLAMP(params->wave_volume + inc, 0, 4); } break; | 1293 | case 6: { params->wave_volume = CLAMP(params->wave_volume + inc, 0, 4); } break; |
1294 | case 7: { params->wave_attack = CLAMP(params->wave_attack + inc, 0, 24); } break; | ||
1295 | case 8: { params->wave_decay = CLAMP(params->wave_decay + inc, 0, 24); } break; | ||
1300 | case 9: { params->pan = CLAMP(params->pan + inc, -1, 1); } break; | 1296 | case 9: { params->pan = CLAMP(params->pan + inc, -1, 1); } break; |
1301 | } | 1297 | } |
1302 | redraw_params = true; | 1298 | redraw_params = true; |
@@ -1475,6 +1471,12 @@ handle_param_selection_ch3() { | |||
1475 | case 6: { | 1471 | case 6: { |
1476 | pat->ch3.params[i].wave_volume = ch3_params.wave_volume; | 1472 | pat->ch3.params[i].wave_volume = ch3_params.wave_volume; |
1477 | } break; | 1473 | } break; |
1474 | case 7: { | ||
1475 | pat->ch3.params[i].wave_attack = ch3_params.wave_attack; | ||
1476 | } break; | ||
1477 | case 8: { | ||
1478 | pat->ch3.params[i].wave_decay = ch3_params.wave_decay; | ||
1479 | } break; | ||
1478 | case 9: { | 1480 | case 9: { |
1479 | pat->ch3.params[i].pan = ch3_params.pan; | 1481 | pat->ch3.params[i].pan = ch3_params.pan; |
1480 | } break; | 1482 | } break; |
@@ -1516,13 +1518,13 @@ handle_param_selection_ch4() { | |||
1516 | 1518 | ||
1517 | void | 1519 | void |
1518 | handle_param_selection_sq1() { | 1520 | handle_param_selection_sq1() { |
1519 | ChannelSquareParams *params = &patterns[pattern_selection_loc].ch1.params[trig_selection_loc]; | 1521 | ChannelSquare1Params *params = &patterns[pattern_selection_loc].ch1.params[trig_selection_loc]; |
1520 | set_param_selection_sq1(params, handle_trigger_selection); | 1522 | set_param_selection_sq1(params, handle_trigger_selection); |
1521 | } | 1523 | } |
1522 | 1524 | ||
1523 | void | 1525 | void |
1524 | handle_param_selection_sq2() { | 1526 | handle_param_selection_sq2() { |
1525 | ChannelSquareParams *params = &patterns[pattern_selection_loc].ch2.params[trig_selection_loc]; | 1527 | ChannelSquare2Params *params = &patterns[pattern_selection_loc].ch2.params[trig_selection_loc]; |
1526 | set_param_selection_sq2(params, handle_trigger_selection); | 1528 | set_param_selection_sq2(params, handle_trigger_selection); |
1527 | } | 1529 | } |
1528 | 1530 | ||
@@ -1543,7 +1545,7 @@ nudge_trigs(int cur_loc, int next_loc) { | |||
1543 | Pattern *pat = &patterns[pattern_selection_loc]; | 1545 | Pattern *pat = &patterns[pattern_selection_loc]; |
1544 | switch (channel_selection_loc) { | 1546 | switch (channel_selection_loc) { |
1545 | case 0: { | 1547 | case 0: { |
1546 | ChannelSquareParams cur_params = pat->ch1.params[cur_loc]; | 1548 | ChannelSquare1Params cur_params = pat->ch1.params[cur_loc]; |
1547 | TriggerNote cur_trig = pat->ch1.notes[cur_loc]; | 1549 | TriggerNote cur_trig = pat->ch1.notes[cur_loc]; |
1548 | pat->ch1.params[cur_loc] = pat->ch1.params[next_loc]; | 1550 | pat->ch1.params[cur_loc] = pat->ch1.params[next_loc]; |
1549 | pat->ch1.notes[cur_loc] = pat->ch1.notes[next_loc]; | 1551 | pat->ch1.notes[cur_loc] = pat->ch1.notes[next_loc]; |
@@ -1551,7 +1553,7 @@ nudge_trigs(int cur_loc, int next_loc) { | |||
1551 | pat->ch1.notes[next_loc] = cur_trig; | 1553 | pat->ch1.notes[next_loc] = cur_trig; |
1552 | } break; | 1554 | } break; |
1553 | case 1: { | 1555 | case 1: { |
1554 | ChannelSquareParams cur_params = pat->ch2.params[cur_loc]; | 1556 | ChannelSquare2Params cur_params = pat->ch2.params[cur_loc]; |
1555 | TriggerNote cur_trig = pat->ch2.notes[cur_loc]; | 1557 | TriggerNote cur_trig = pat->ch2.notes[cur_loc]; |
1556 | pat->ch2.params[cur_loc] = pat->ch2.params[next_loc]; | 1558 | pat->ch2.params[cur_loc] = pat->ch2.params[next_loc]; |
1557 | pat->ch2.notes[cur_loc] = pat->ch2.notes[next_loc]; | 1559 | pat->ch2.notes[cur_loc] = pat->ch2.notes[next_loc]; |