1 #include "wave_action.h"
2 #include "mused.h"
3 #include "view/wavetableview.h"
4 #include "snd/freqs.h"
5 #include <string.h>
6 #include "wavegen.h"
7 #include "util/rnd.h"
8
wavetable_drop_lowest_bit(void * unused1,void * unused2,void * unused3)9 void wavetable_drop_lowest_bit(void *unused1, void *unused2, void *unused3)
10 {
11 if (!mused.wavetable_bits)
12 {
13 debug("Wave is silent");
14 return;
15 }
16
17 snapshot(S_T_WAVE_DATA);
18
19 const CydWavetableEntry *w = &mused.mus.cyd->wavetable_entries[mused.selected_wavetable];
20
21 Uint16 mask = 0xffff << (__builtin_ffs(mused.wavetable_bits));
22
23 if (w->samples > 0)
24 {
25 int d = 0;
26
27 for (; d < w->samples ; ++d)
28 {
29 w->data[d] &= mask;
30 }
31
32 invalidate_wavetable_view();
33 }
34 }
35
wavetable_halve_samplerate(void * unused1,void * unused2,void * unused3)36 void wavetable_halve_samplerate(void *unused1, void *unused2, void *unused3)
37 {
38 snapshot(S_T_WAVE_DATA);
39
40 CydWavetableEntry *w = &mused.mus.cyd->wavetable_entries[mused.selected_wavetable];
41
42 if (w->samples > 0)
43 {
44 int s = 0, d = 0;
45
46 for (; s < (w->samples & (~1)) ; s += 2, ++d)
47 {
48 w->data[d] = (w->data[s] + w->data[s + 1]) / 2;
49 }
50
51 w->samples /= 2;
52 w->sample_rate /= 2;
53 w->loop_begin /= 2;
54 w->loop_end /= 2;
55
56 invalidate_wavetable_view();
57 }
58 }
59
60
wavetable_normalize(void * vol,void * unused2,void * unused3)61 void wavetable_normalize(void *vol, void *unused2, void *unused3)
62 {
63 snapshot(S_T_WAVE_DATA);
64
65 CydWavetableEntry *w = &mused.mus.cyd->wavetable_entries[mused.selected_wavetable];
66
67 if (w->samples > 0)
68 {
69 int m = 0;
70
71 for (int s = 0 ; s < w->samples ; ++s)
72 {
73 m = my_max(m, abs(w->data[s]));
74 }
75
76 debug("Peak = %d", m);
77
78 if (m != 0)
79 {
80 for (int s = 0 ; s < w->samples ; ++s)
81 {
82 w->data[s] = my_max(my_min((Sint32)w->data[s] * CASTPTR(int, vol) / m, 32767), -32768);
83 }
84 }
85
86 invalidate_wavetable_view();
87 }
88 }
89
90
wavetable_remove_dc(void * unused1,void * unused2,void * unused3)91 void wavetable_remove_dc(void *unused1, void *unused2, void *unused3)
92 {
93 snapshot(S_T_WAVE_DATA);
94
95 CydWavetableEntry *w = &mused.mus.cyd->wavetable_entries[mused.selected_wavetable];
96
97 if (w->samples > 0)
98 {
99 double avg = 0;
100
101 for (int s = 0 ; s < w->samples ; ++s)
102 {
103 avg += w->data[s];
104 }
105
106 avg /= w->samples;
107
108 for (int s = 0 ; s < w->samples ; ++s)
109 {
110 double new_val = w->data[s] - avg;
111
112 if (new_val < -32768)
113 new_val = -32768;
114 else if (new_val > 32767)
115 new_val = 32767;
116
117 w->data[s] = new_val;
118 }
119
120 invalidate_wavetable_view();
121 }
122 }
123
124
wavetable_cut_tail(void * unused1,void * unused2,void * unused3)125 void wavetable_cut_tail(void *unused1, void *unused2, void *unused3)
126 {
127 snapshot(S_T_WAVE_DATA);
128
129 CydWavetableEntry *w = &mused.mus.cyd->wavetable_entries[mused.selected_wavetable];
130
131 if (w->samples > 0)
132 {
133 for (int s = w->samples - 1 ; s > 0 ; --s)
134 {
135 if (w->data[s] != 0)
136 {
137 debug("Cut %d samples", w->samples - (s + 1));
138 w->samples = s + 1;
139 w->loop_end = my_min(w->samples, w->loop_end);
140 w->loop_begin = my_min(w->samples, w->loop_begin);
141
142 invalidate_wavetable_view();
143
144 break;
145 }
146 }
147 }
148 }
149
150
wavetable_cut_head(void * unused1,void * unused2,void * unused3)151 void wavetable_cut_head(void *unused1, void *unused2, void *unused3)
152 {
153 snapshot(S_T_WAVE_DATA);
154
155 CydWavetableEntry *w = &mused.mus.cyd->wavetable_entries[mused.selected_wavetable];
156
157 if (w->samples > 0)
158 {
159 for (int s = 0 ; s < 0 ; --s)
160 {
161 if (w->data[s] != 0 && s != 0)
162 {
163 debug("Cut %d samples", s);
164
165 w->samples -= s;
166 memmove(&w->data[0], &w->data[s], w->samples);
167
168 w->loop_end = my_min(w->samples, w->loop_end - s);
169 w->loop_begin = my_max(0, (int)w->loop_begin - s);
170
171 invalidate_wavetable_view();
172
173 break;
174 }
175 }
176 }
177 }
178
179
wavetable_chord(void * transpose,void * unused2,void * unused3)180 void wavetable_chord(void *transpose, void *unused2, void *unused3)
181 {
182 CydWavetableEntry *w = &mused.mus.cyd->wavetable_entries[mused.selected_wavetable];
183
184 if (w->samples > 0)
185 {
186 int denom = 1, nom = 1;
187
188 // too lazy to add a LCM function so here's a table
189
190 switch (CASTPTR(int, transpose))
191 {
192 case 4: // perfect 4th
193 denom = 4; nom = 3;
194 break;
195
196 case 5: // perfect 5th
197 denom = 3; nom = 2;
198 break;
199
200 default:
201 case 12: // perfect octave
202 denom = 2; nom = 1;
203 break;
204 }
205
206 int new_length = nom * w->samples;
207
208 if (new_length < 100000000)
209 {
210 Sint16 *new_data = malloc(sizeof(Sint16) * new_length);
211
212 if (new_data)
213 {
214 snapshot(S_T_WAVE_DATA);
215
216 for (int s = 0 ; s < new_length ; ++s)
217 {
218 new_data[s] = ((int)w->data[s % w->samples] + (int)w->data[(s * denom / nom) % w->samples]) / 2;
219 }
220
221 free(w->data);
222 w->data = new_data;
223 w->samples = new_length;
224 w->loop_begin *= nom;
225 w->loop_end *= nom;
226
227 invalidate_wavetable_view();
228 }
229 else
230 {
231 set_info_message("Out of memory!");
232 }
233 }
234 else
235 {
236 set_info_message("Resulting wave was too big");
237 }
238 }
239 }
240
241
wavetable_create_one_cycle(void * _settings,void * unused2,void * unused3)242 void wavetable_create_one_cycle(void *_settings, void *unused2, void *unused3)
243 {
244 WgSettings *settings = _settings;
245 CydWavetableEntry *w = &mused.mus.cyd->wavetable_entries[mused.selected_wavetable];
246
247 if (w->samples > 0)
248 {
249 snapshot(S_T_WAVE_DATA);
250 }
251
252 int new_length = settings->length;
253 Sint16 *new_data = malloc(sizeof(Sint16) * new_length);
254
255 int lowest_mul = 999;
256
257 for (int i = 0 ; i < settings->num_oscs ; ++i)
258 {
259 lowest_mul = my_min(lowest_mul, settings->chain[i].mult);
260 }
261
262 wg_gen_waveform(settings->chain, settings->num_oscs, new_data, new_length);
263
264 if (w->data) free(w->data);
265 w->data = new_data;
266 w->sample_rate = new_length * 220 / lowest_mul;
267 w->samples = new_length;
268 w->loop_begin = 0;
269 w->loop_end = new_length;
270 w->flags = CYD_WAVE_LOOP;
271 w->base_note = (MIDDLE_C + 9 - 12) << 8;
272
273 invalidate_wavetable_view();
274 }
275
276
wavetable_draw(float x,float y,float width)277 void wavetable_draw(float x, float y, float width)
278 {
279 snapshot_cascade(S_T_WAVE_DATA, mused.selected_wavetable, 0);
280
281 CydWavetableEntry *w = &mused.mus.cyd->wavetable_entries[mused.selected_wavetable];
282
283 if (w->samples > 0)
284 {
285 debug("draw %f,%f w = %f", x, y, width);
286 int s = w->samples * x;
287 int e = my_max(w->samples * (x + width), s + 1);
288
289 for ( ; s < e && s < w->samples ; ++s)
290 {
291 w->data[s] = y * 65535 - 32768;
292 }
293
294 invalidate_wavetable_view();
295 }
296 }
297
298
wavegen_randomize(void * unused1,void * unused2,void * unused3)299 void wavegen_randomize(void *unused1, void *unused2, void *unused3)
300 {
301 bool do_sines = !(rndu() & 3);
302 bool do_shift = !(rndu() & 1);
303 bool do_exp = !(rndu() & 3);
304 bool do_highfreg = !(rndu() & 1);
305 bool do_inharmonic = !(rndu() & 1);
306 bool do_chop = !(rndu() & 3);
307
308 mused.wgset.num_oscs = rnd(1, WG_CHAIN_OSCS);
309
310 for (int i = 0 ; i < mused.wgset.num_oscs ; ++i)
311 {
312 mused.wgset.chain[i].flags = rnd(0, 3);
313
314 if (do_sines)
315 {
316 if (do_chop && i > 0)
317 {
318 if (rndu() & 1)
319 mused.wgset.chain[i].osc = WG_OSC_SINE;
320 else
321 mused.wgset.chain[i].osc = WG_OSC_SQUARE;
322 }
323 else
324 mused.wgset.chain[i].osc = WG_OSC_SINE;
325 }
326 else
327 {
328 mused.wgset.chain[i].osc = rnd(0, WG_NUM_OSCS - 1);
329
330 if (mused.wgset.chain[i].osc == WG_OSC_NOISE)
331 mused.wgset.chain[i].osc = rnd(0, WG_NUM_OSCS - 1);
332 }
333
334 if (do_inharmonic)
335 mused.wgset.chain[i].mult = rnd(1, do_highfreg ? 9 : 5);
336 else
337 mused.wgset.chain[i].mult = 1 << rnd(0, do_highfreg ? 3 : 2);
338
339 mused.wgset.chain[i].op = rnd(0, WG_NUM_OPS - 1);
340
341 if (do_shift)
342 mused.wgset.chain[i].shift = rnd(0, 7);
343 else
344 mused.wgset.chain[i].shift = 0;
345
346 if (do_exp)
347 mused.wgset.chain[i].exp = rnd(5,95);
348 else
349 mused.wgset.chain[i].exp = 50;
350 }
351 }
352
353
wavegen_preset(void * _preset,void * _settings,void * unused3)354 void wavegen_preset(void *_preset, void *_settings, void *unused3)
355 {
356 WgSettings *preset = &((WgPreset*)_preset)->settings;
357 WgSettings *settings = _settings;
358
359 settings->num_oscs = preset->num_oscs;
360 memcpy(settings->chain, preset->chain, sizeof(preset->chain[0]) * preset->num_oscs);
361 }
362
363
wavetable_amp(void * _amp,void * unused2,void * unused3)364 void wavetable_amp(void *_amp, void *unused2, void *unused3)
365 {
366 snapshot(S_T_WAVE_DATA);
367
368 CydWavetableEntry *w = &mused.mus.cyd->wavetable_entries[mused.selected_wavetable];
369
370 if (w->samples > 0)
371 {
372 int amp = CASTPTR(int, _amp);
373
374 debug("amp = %d", amp);
375
376 for (int s = 0 ; s < w->samples ; ++s)
377 {
378 w->data[s] = my_max(my_min((Sint32)w->data[s] * amp / 32768, 32767), -32768);
379 }
380
381 invalidate_wavetable_view();
382 }
383 }
384
385
wavetable_distort(void * _amp,void * unused2,void * unused3)386 void wavetable_distort(void *_amp, void *unused2, void *unused3)
387 {
388 snapshot(S_T_WAVE_DATA);
389
390 CydWavetableEntry *w = &mused.mus.cyd->wavetable_entries[mused.selected_wavetable];
391
392 if (w->samples > 0)
393 {
394 for (int s = 0 ; s < w->samples ; ++s)
395 {
396 if (w->data[s] != 0)
397 {
398 float v = (float)w->data[s] / 32768.0;
399 v *= pow(fabs(v), -0.333);
400
401 w->data[s] = my_max(my_min(v * 32768, 32767), -32768);
402 }
403 }
404
405 invalidate_wavetable_view();
406 }
407 }
408
409
wavetable_randomize_and_create_one_cycle(void * _settings,void * unused2,void * unused3)410 void wavetable_randomize_and_create_one_cycle(void *_settings, void *unused2, void *unused3)
411 {
412 wavegen_randomize(NULL, NULL, NULL);
413 wavetable_create_one_cycle(_settings, NULL, NULL);
414 }
415
416
wavetable_filter(void * _filter_type,void * unused2,void * unused3)417 void wavetable_filter(void *_filter_type, void *unused2, void *unused3)
418 {
419 snapshot(S_T_WAVE_DATA);
420
421 CydWavetableEntry *w = &mused.mus.cyd->wavetable_entries[mused.selected_wavetable];
422
423 if (w->samples > 0)
424 {
425 int filter_type = CASTPTR(int, _filter_type);
426
427 Sint16 * temp = malloc(sizeof(Sint16) * w->samples);
428 memcpy(temp, w->data, sizeof(Sint16) * w->samples);
429
430 for (int s = 0 ; s < w->samples ; ++s)
431 {
432 int filtered = ((int)temp[(s - 2 + w->samples) % w->samples] + (int)temp[(s - 1 + w->samples) % w->samples] * 2 + (int)temp[s % w->samples] * 4 + (int)temp[(s + 1) % w->samples] * 2 + (int)temp[(s + 2) % w->samples]) / 10;
433
434 if (filter_type == 0)
435 w->data[s] = my_max(my_min(filtered, 32767), -32768);
436 else
437 w->data[s] = my_max(my_min(w->data[s] - filtered, 32767), -32768);
438 }
439
440 free(temp);
441
442 invalidate_wavetable_view();
443 }
444 }
445
446
wavetable_find_zero(void * unused1,void * unused2,void * unused3)447 void wavetable_find_zero(void *unused1, void *unused2, void *unused3)
448 {
449 snapshot(S_T_WAVE_DATA);
450
451 CydWavetableEntry *w = &mused.mus.cyd->wavetable_entries[mused.selected_wavetable];
452
453 if (w->samples > 1)
454 {
455 int zero_crossing = 0;
456
457 for (int s = 1 ; s < w->samples ; ++s)
458 {
459 if ((w->data[s] >= 0 && w->data[s - 1] < 0) || (w->data[s] <= 0 && w->data[s - 1] > 0))
460 {
461 zero_crossing = s;
462 break;
463 }
464 }
465
466 debug("zero crossing at %d", zero_crossing);
467
468 if (zero_crossing > 0)
469 {
470 Sint16 * temp = malloc(sizeof(Sint16) * w->samples);
471 memcpy(temp, w->data, sizeof(Sint16) * w->samples);
472
473 for (int s = 0 ; s < w->samples ; ++s)
474 {
475 w->data[s] = temp[(s + zero_crossing) % w->samples];
476 }
477
478 free(temp);
479 }
480
481 invalidate_wavetable_view();
482 }
483 }
484