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