1 /*
2  * Schism Tracker - a cross-platform Impulse Tracker clone
3  * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com>
4  * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org>
5  * copyright (c) 2009 Storlek & Mrs. Brisby
6  * copyright (c) 2010-2012 Storlek
7  * URL: http://schismtracker.org/
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #include "headers.h"
25 
26 #include "it.h"
27 #include "util.h"
28 #include "song.h"
29 #include "cmixer.h"
30 #include "sample-edit.h"
31 
32 #include "sdlmain.h"
33 
34 /* --------------------------------------------------------------------- */
35 /* helper functions */
36 
_minmax_8(signed char * data,unsigned long length,signed char * min,signed char * max)37 static void _minmax_8(signed char *data, unsigned long length, signed char *min, signed char *max)
38 {
39 	unsigned long pos = length;
40 
41 	*min = 127;
42 	*max = -128;
43 	while (pos) {
44 		pos--;
45 		if (data[pos] < *min)
46 			*min = data[pos];
47 		else if (data[pos] > *max)
48 			*max = data[pos];
49 	}
50 }
51 
_minmax_16(signed short * data,unsigned long length,signed short * min,signed short * max)52 static void _minmax_16(signed short *data, unsigned long length, signed short *min, signed short *max)
53 {
54 	unsigned long pos = length;
55 
56 	*min = 32767;
57 	*max = -32768;
58 	while (pos) {
59 		pos--;
60 		if (data[pos] < *min)
61 			*min = data[pos];
62 		else if (data[pos] > *max)
63 			*max = data[pos];
64 	}
65 }
66 
67 /* --------------------------------------------------------------------- */
68 /* sign convert (a.k.a. amiga flip) */
69 
_sign_convert_8(signed char * data,unsigned long length)70 static void _sign_convert_8(signed char *data, unsigned long length)
71 {
72 	unsigned long pos = length;
73 
74 	while (pos) {
75 		pos--;
76 		data[pos] += 128;
77 	}
78 }
79 
_sign_convert_16(signed short * data,unsigned long length)80 static void _sign_convert_16(signed short *data, unsigned long length)
81 {
82 	unsigned long pos = length;
83 
84 	while (pos) {
85 		pos--;
86 		data[pos] += 32768;
87 	}
88 }
89 
sample_sign_convert(song_sample_t * sample)90 void sample_sign_convert(song_sample_t * sample)
91 {
92 	song_lock_audio();
93 	status.flags |= SONG_NEEDS_SAVE;
94 	if (sample->flags & CHN_16BIT)
95 		_sign_convert_16((signed short *) sample->data,
96 			sample->length * ((sample->flags & CHN_STEREO) ? 2 : 1));
97 	else
98 		_sign_convert_8(sample->data, sample->length * ((sample->flags & CHN_STEREO) ? 2 : 1));
99 	song_unlock_audio();
100 }
101 
102 /* --------------------------------------------------------------------- */
103 /* from the back to the front */
104 
_reverse_8(signed char * data,unsigned long length)105 static void _reverse_8(signed char *data, unsigned long length)
106 {
107 	signed char tmp;
108 	unsigned long lpos = 0, rpos = length - 1;
109 
110 	while (lpos < rpos) {
111 		tmp = data[lpos];
112 		data[lpos] = data[rpos];
113 		data[rpos] = tmp;
114 		lpos++;
115 		rpos--;
116 	}
117 }
118 
_reverse_16(signed short * data,unsigned long length)119 static void _reverse_16(signed short *data, unsigned long length)
120 {
121 	signed short tmp;
122 	unsigned long lpos = 0, rpos = length - 1;
123 
124 	while (lpos < rpos) {
125 		tmp = data[lpos];
126 		data[lpos] = data[rpos];
127 		data[rpos] = tmp;
128 		lpos++;
129 		rpos--;
130 	}
131 }
_reverse_32(signed int * data,unsigned long length)132 static void _reverse_32(signed int *data, unsigned long length)
133 {
134 	signed int tmp;
135 	unsigned long lpos = 0, rpos = length - 1;
136 
137 	while (lpos < rpos) {
138 		tmp = data[lpos];
139 		data[lpos] = data[rpos];
140 		data[rpos] = tmp;
141 		lpos++;
142 		rpos--;
143 	}
144 }
145 
sample_reverse(song_sample_t * sample)146 void sample_reverse(song_sample_t * sample)
147 {
148 	unsigned long tmp;
149 
150 	song_lock_audio();
151 	status.flags |= SONG_NEEDS_SAVE;
152 
153 	if (sample->flags & CHN_STEREO) {
154 		if (sample->flags & CHN_16BIT)
155 			_reverse_32((signed int *)sample->data, sample->length);
156 		else
157 			_reverse_16((signed short *) sample->data, sample->length);
158 	} else {
159 		if (sample->flags & CHN_16BIT)
160 			_reverse_16((signed short *) sample->data, sample->length);
161 		else
162 			_reverse_8(sample->data, sample->length);
163 	}
164 
165 	tmp = sample->length - sample->loop_start;
166 	sample->loop_start = sample->length - sample->loop_end;
167 	sample->loop_end = tmp;
168 
169 	tmp = sample->length - sample->sustain_start;
170 	sample->sustain_start = sample->length - sample->sustain_end;
171 	sample->sustain_end = tmp;
172 
173 	song_unlock_audio();
174 }
175 
176 /* --------------------------------------------------------------------- */
177 
178 /* if convert_data is nonzero, the sample data is modified (so it sounds
179  * the same); otherwise, the sample length is changed and the data is
180  * left untouched. */
181 
_quality_convert_8to16(signed char * idata,signed short * odata,unsigned long length)182 static void _quality_convert_8to16(signed char *idata, signed short *odata, unsigned long length)
183 {
184 	unsigned long pos = length;
185 
186 	while (pos) {
187 		pos--;
188 		odata[pos] = idata[pos] << 8;
189 	}
190 }
191 
_quality_convert_16to8(signed short * idata,signed char * odata,unsigned long length)192 static void _quality_convert_16to8(signed short *idata, signed char *odata, unsigned long length)
193 {
194 	unsigned long pos = length;
195 
196 	while (pos) {
197 		pos--;
198 		odata[pos] = idata[pos] >> 8;
199 	}
200 }
201 
sample_toggle_quality(song_sample_t * sample,int convert_data)202 void sample_toggle_quality(song_sample_t * sample, int convert_data)
203 {
204 	signed char *odata;
205 
206 	song_lock_audio();
207 
208 	// stop playing the sample because we'll be reallocating and/or changing lengths
209 	csf_stop_sample(current_song, sample);
210 
211 	sample->flags ^= CHN_16BIT;
212 
213 	status.flags |= SONG_NEEDS_SAVE;
214 	if (convert_data) {
215 		odata = csf_allocate_sample(sample->length
216 			* ((sample->flags & CHN_16BIT) ? 2 : 1)
217 			* ((sample->flags & CHN_STEREO) ? 2 : 1));
218 		if (sample->flags & CHN_16BIT) {
219 			_quality_convert_8to16(sample->data, (signed short *) odata,
220 				sample->length * ((sample->flags & CHN_STEREO) ? 2 : 1));
221 		} else {
222 			_quality_convert_16to8((signed short *) sample->data, odata,
223 				sample->length * ((sample->flags & CHN_STEREO) ? 2 : 1));
224 		}
225 		csf_free_sample(sample->data);
226 		sample->data = odata;
227 	} else {
228 		if (sample->flags & CHN_16BIT) {
229 			sample->length >>= 1;
230 			sample->loop_start >>= 1;
231 			sample->loop_end >>= 1;
232 			sample->sustain_start >>= 1;
233 			sample->sustain_end >>= 1;
234 		} else {
235 			sample->length <<= 1;
236 			sample->loop_start <<= 1;
237 			sample->loop_end <<= 1;
238 			sample->sustain_start <<= 1;
239 			sample->sustain_end <<= 1;
240 		}
241 	}
242 	song_unlock_audio();
243 }
244 
245 /* --------------------------------------------------------------------- */
246 /* centralise (correct dc offset) */
247 
_centralise_8(signed char * data,unsigned long length)248 static void _centralise_8(signed char *data, unsigned long length)
249 {
250 	unsigned long pos = length;
251 	signed char min, max;
252 	int offset;
253 
254 	_minmax_8(data, length, &min, &max);
255 
256 	offset = (max + min + 1) >> 1;
257 	if (offset == 0)
258 		return;
259 
260 	pos = length;
261 	while (pos) {
262 		pos--;
263 		data[pos] -= offset;
264 	}
265 }
266 
_centralise_16(signed short * data,unsigned long length)267 static void _centralise_16(signed short *data, unsigned long length)
268 {
269 	unsigned long pos = length;
270 	signed short min, max;
271 	int offset;
272 
273 	_minmax_16(data, length, &min, &max);
274 
275 	while (pos) {
276 		pos--;
277 		if (data[pos] < min)
278 			min = data[pos];
279 		else if (data[pos] > max)
280 			max = data[pos];
281 	}
282 
283 	offset = (max + min + 1) >> 1;
284 	if (offset == 0)
285 		return;
286 
287 	pos = length;
288 	while (pos) {
289 		pos--;
290 		data[pos] -= offset;
291 	}
292 }
293 
sample_centralise(song_sample_t * sample)294 void sample_centralise(song_sample_t * sample)
295 {
296 	song_lock_audio();
297 	status.flags |= SONG_NEEDS_SAVE;
298 	if (sample->flags & CHN_16BIT)
299 		_centralise_16((signed short *) sample->data,
300 			sample->length * ((sample->flags & CHN_STEREO) ? 2 : 1));
301 	else
302 		_centralise_8(sample->data, sample->length * ((sample->flags & CHN_STEREO) ? 2 : 1));
303 	song_unlock_audio();
304 }
305 
306 /* --------------------------------------------------------------------- */
307 /* downmix stereo to mono */
308 
_downmix_8(signed char * data,unsigned long length)309 static void _downmix_8(signed char *data, unsigned long length)
310 {
311 	unsigned long i, j;
312 	for (i = j = 0; j < length; j++, i += 2)
313 		data[j] = (data[i] + data[i + 1]) / 2;
314 }
315 
_downmix_16(signed short * data,unsigned long length)316 static void _downmix_16(signed short *data, unsigned long length)
317 {
318 	unsigned long i, j;
319 	for (i = j = 0; j < length; j++, i += 2)
320 		data[j] = (data[i] + data[i + 1]) / 2;
321 }
322 
sample_downmix(song_sample_t * sample)323 void sample_downmix(song_sample_t *sample)
324 {
325 	if (!(sample->flags & CHN_STEREO))
326 		return; /* what are we doing here with a mono sample? */
327 	song_lock_audio();
328 	status.flags |= SONG_NEEDS_SAVE;
329 	if (sample->flags & CHN_16BIT)
330 		_downmix_16((signed short *) sample->data, sample->length);
331 	else
332 		_downmix_8(sample->data, sample->length);
333 	sample->flags &= ~CHN_STEREO;
334 	song_unlock_audio();
335 }
336 
337 /* --------------------------------------------------------------------- */
338 /* amplify (or attenuate) */
339 
_amplify_8(signed char * data,unsigned long length,int percent)340 static void _amplify_8(signed char *data, unsigned long length, int percent)
341 {
342 	unsigned long pos = length;
343 	int b;
344 
345 	while (pos) {
346 		pos--;
347 		b = data[pos] * percent / 100;
348 		data[pos] = CLAMP(b, -128, 127);
349 	}
350 }
351 
_amplify_16(signed short * data,unsigned long length,int percent)352 static void _amplify_16(signed short *data, unsigned long length, int percent)
353 {
354 	unsigned long pos = length;
355 	int b;
356 
357 	while (pos) {
358 		pos--;
359 		b = data[pos] * percent / 100;
360 		data[pos] = CLAMP(b, -32768, 32767);
361 	}
362 }
363 
sample_amplify(song_sample_t * sample,int percent)364 void sample_amplify(song_sample_t * sample, int percent)
365 {
366 	song_lock_audio();
367 	status.flags |= SONG_NEEDS_SAVE;
368 	if (sample->flags & CHN_16BIT)
369 		_amplify_16((signed short *) sample->data,
370 			sample->length * ((sample->flags & CHN_STEREO) ? 2 : 1), percent);
371 	else
372 		_amplify_8(sample->data, sample->length * ((sample->flags & CHN_STEREO) ? 2 : 1), percent);
373 	song_unlock_audio();
374 }
375 
_get_amplify_8(signed char * data,unsigned long length)376 static int _get_amplify_8(signed char *data, unsigned long length)
377 {
378 	signed char min, max;
379 	_minmax_8(data, length, &min, &max);
380 	max = MAX(max, -min);
381 	return max ? 128 * 100 / max : 100;
382 }
383 
_get_amplify_16(signed short * data,unsigned long length)384 static int _get_amplify_16(signed short *data, unsigned long length)
385 {
386 	signed short min, max;
387 	_minmax_16(data, length, &min, &max);
388 	max = MAX(max, -min);
389 	return max ? 32768 * 100 / max : 100;
390 }
391 
sample_get_amplify_amount(song_sample_t * sample)392 int sample_get_amplify_amount(song_sample_t *sample)
393 {
394 	int percent;
395 
396 	if (sample->flags & CHN_16BIT)
397 		percent = _get_amplify_16((signed short *) sample->data,
398 			sample->length * ((sample->flags & CHN_STEREO) ? 2 : 1));
399 	else
400 		percent = _get_amplify_8(sample->data,
401 			sample->length * ((sample->flags & CHN_STEREO) ? 2 : 1));
402 
403 	if (percent < 100) percent = 100;
404 	return percent;
405 }
406 
407 /* --------------------------------------------------------------------- */
408 /* useful for importing delta-encoded raw data */
409 
_delta_decode_8(signed char * data,unsigned long length)410 static void _delta_decode_8(signed char *data, unsigned long length)
411 {
412 	unsigned long pos;
413 	signed char o = 0, n;
414 
415 	for (pos = 1; pos < length; pos++) {
416 		n = data[pos] + o;
417 		data[pos] = n;
418 		o = n;
419 	}
420 }
421 
_delta_decode_16(signed short * data,unsigned long length)422 static void _delta_decode_16(signed short *data, unsigned long length)
423 {
424 	unsigned long pos;
425 	signed short o = 0, n;
426 
427 	for (pos = 1; pos < length; pos++) {
428 		n = data[pos] + o;
429 		data[pos] = n;
430 		o = n;
431 	}
432 }
433 
sample_delta_decode(song_sample_t * sample)434 void sample_delta_decode(song_sample_t * sample)
435 {
436 	song_lock_audio();
437 	status.flags |= SONG_NEEDS_SAVE;
438 	if (sample->flags & CHN_16BIT)
439 		_delta_decode_16((signed short *) sample->data,
440 			sample->length * ((sample->flags & CHN_STEREO) ? 2 : 1));
441 	else
442 		_delta_decode_8(sample->data, sample->length * ((sample->flags & CHN_STEREO) ? 2 : 1));
443 	song_unlock_audio();
444 }
445 
446 /* --------------------------------------------------------------------- */
447 /* surround flipping (probably useless with the S91 effect, but why not) */
448 
_invert_8(signed char * data,unsigned long length)449 static void _invert_8(signed char *data, unsigned long length)
450 {
451 	unsigned long pos = length;
452 
453 	while (pos) {
454 		pos--;
455 		data[pos] = ~data[pos];
456 	}
457 }
458 
_invert_16(signed short * data,unsigned long length)459 static void _invert_16(signed short *data, unsigned long length)
460 {
461 	unsigned long pos = length;
462 
463 	while (pos) {
464 		pos--;
465 		data[pos] = ~data[pos];
466 	}
467 }
468 
469 
_resize_16(signed short * dst,unsigned long newlen,signed short * src,unsigned long oldlen,unsigned int is_stereo)470 static void _resize_16(signed short *dst, unsigned long newlen,
471 		signed short *src, unsigned long oldlen, unsigned int is_stereo)
472 {
473 	unsigned int i;
474 	double factor = (double)oldlen / (double)newlen;
475 	if (is_stereo) for (i = 0; i < newlen; i++)
476 	{
477 		unsigned int pos = 2*(unsigned int)((double)i * factor);
478 		dst[2*i] = src[pos];
479 		dst[2*i+1] = src[pos+1];
480 	}
481 	else for (i = 0; i < newlen; i++)
482 	{
483 		dst[i] = src[(unsigned int)((double)i * factor)];
484 	}
485 }
_resize_8(signed char * dst,unsigned long newlen,signed char * src,unsigned long oldlen,unsigned int is_stereo)486 static void _resize_8(signed char *dst, unsigned long newlen,
487 		signed char *src, unsigned long oldlen, unsigned int is_stereo)
488 {
489 	unsigned int i;
490 	double factor = (double)oldlen / (double)newlen;
491 	if (is_stereo) {
492 		for (i = 0; i < newlen; i++) {
493 			unsigned int pos = 2*(unsigned int)((double)i * factor);
494 			dst[2*i] = src[pos];
495 			dst[2*i+1] = src[pos+1];
496 		}
497 	} else {
498 		for (i = 0; i < newlen; i++) {
499 			dst[i] = src[(unsigned int)((double)i * factor)];
500 		}
501 	}
502 }
_resize_8aa(signed char * dst,unsigned long newlen,signed char * src,unsigned long oldlen,unsigned int is_stereo)503 static void _resize_8aa(signed char *dst, unsigned long newlen,
504 		signed char *src, unsigned long oldlen, unsigned int is_stereo)
505 {
506 	if (is_stereo)
507 		ResampleStereo8BitFirFilter(src, dst, oldlen, newlen);
508 	else
509 		ResampleMono8BitFirFilter(src, dst, oldlen, newlen);
510 }
_resize_16aa(signed short * dst,unsigned long newlen,signed short * src,unsigned long oldlen,unsigned int is_stereo)511 static void _resize_16aa(signed short *dst, unsigned long newlen,
512 		signed short *src, unsigned long oldlen, unsigned int is_stereo)
513 {
514 	if (is_stereo)
515 		ResampleStereo16BitFirFilter(src, dst, oldlen, newlen);
516 	else
517 		ResampleMono16BitFirFilter(src, dst, oldlen, newlen);
518 }
519 
520 
521 
sample_resize(song_sample_t * sample,unsigned long newlen,int aa)522 void sample_resize(song_sample_t * sample, unsigned long newlen, int aa)
523 {
524 	int bps;
525 	signed char *d, *z;
526 	unsigned long oldlen;
527 
528 	if (!newlen) return;
529 	if (!sample->data || !sample->length) return;
530 
531 	song_lock_audio();
532 
533 	/* resizing samples while they're playing keeps crashing things.
534 	so here's my "fix": stop the song. --plusminus */
535 	// I suppose that works, but it's slightly annoying, so I'll just stop the sample...
536 	// hopefully this won't (re)introduce crashes. --Storlek
537 	csf_stop_sample(current_song, sample);
538 
539 	bps = (((sample->flags & CHN_STEREO) ? 2 : 1)
540 		* ((sample->flags & CHN_16BIT) ? 2 : 1));
541 
542 	status.flags |= SONG_NEEDS_SAVE;
543 
544 	d = csf_allocate_sample(newlen*bps);
545 	z = sample->data;
546 
547 	sample->c5speed = (unsigned long)((((double)newlen) * ((double)sample->c5speed))
548 			/ ((double)sample->length));
549 
550 	/* scale loop points */
551 	sample->loop_start = (unsigned long)((((double)newlen) * ((double)sample->loop_start))
552 			/ ((double)sample->length));
553 	sample->loop_end = (unsigned long)((((double)newlen) * ((double)sample->loop_end))
554 			/ ((double)sample->length));
555 	sample->sustain_start = (unsigned long)((((double)newlen) * ((double)sample->sustain_start))
556 			/ ((double)sample->length));
557 	sample->sustain_end = (unsigned long)((((double)newlen) * ((double)sample->sustain_end))
558 			/ ((double)sample->length));
559 
560 	oldlen = sample->length;
561 	sample->length = newlen;
562 
563 	if (sample->flags & CHN_16BIT) {
564 		if (aa) {
565 			_resize_16aa((signed short *) d, newlen, (short *) sample->data, oldlen, sample->flags & CHN_STEREO);
566 		} else {
567 			_resize_16((signed short *) d, newlen, (short *) sample->data, oldlen, sample->flags & CHN_STEREO);
568 		}
569 	} else {
570 		if (aa) {
571 			_resize_8aa(d, newlen, sample->data, oldlen, sample->flags & CHN_STEREO);
572 		} else {
573 			_resize_8(d, newlen, sample->data, oldlen, sample->flags & CHN_STEREO);
574 		}
575 	}
576 
577 	sample->data = d;
578 	csf_free_sample(z);
579 	song_unlock_audio();
580 }
581 
sample_invert(song_sample_t * sample)582 void sample_invert(song_sample_t * sample)
583 {
584 	song_lock_audio();
585 	status.flags |= SONG_NEEDS_SAVE;
586 	if (sample->flags & CHN_16BIT)
587 		_invert_16((signed short *) sample->data,
588 			sample->length * ((sample->flags & CHN_STEREO) ? 2 : 1));
589 	else
590 		_invert_8(sample->data, sample->length * ((sample->flags & CHN_STEREO) ? 2 : 1));
591 	song_unlock_audio();
592 }
593 
_mono_lr16(signed short * data,unsigned long length,int shift)594 static void _mono_lr16(signed short *data, unsigned long length, int shift)
595 {
596 	unsigned long i=1, j;
597 	if (shift) { i=0; }
598 	for (j = 0; j < length; j++, i += 2)
599 		data[j] = data[i];
600 }
_mono_lr8(signed char * data,unsigned long length,int shift)601 static void _mono_lr8(signed char *data, unsigned long length, int shift)
602 {
603 	unsigned long i=1, j;
604 	if (shift) { i=0; }
605 	for (j = 0; j < length; j++, i += 2)
606 		data[j] = data[i];
607 }
sample_mono_left(song_sample_t * sample)608 void sample_mono_left(song_sample_t * sample)
609 {
610 	song_lock_audio();
611 	status.flags |= SONG_NEEDS_SAVE;
612 	if (sample->flags & CHN_STEREO) {
613 		if (sample->flags & CHN_16BIT)
614 			_mono_lr16((signed short *)sample->data, sample->length, 1);
615 		else
616 			_mono_lr8((signed char *)sample->data, sample->length, 1);
617 		sample->flags &= ~CHN_STEREO;
618 	}
619 	song_unlock_audio();
620 }
sample_mono_right(song_sample_t * sample)621 void sample_mono_right(song_sample_t * sample)
622 {
623 	song_lock_audio();
624 	status.flags |= SONG_NEEDS_SAVE;
625 	if (sample->flags & CHN_STEREO) {
626 		if (sample->flags & CHN_16BIT)
627 			_mono_lr16((signed short *)sample->data, sample->length, 0);
628 		else
629 			_mono_lr8((signed char *)sample->data, sample->length, 0);
630 		sample->flags &= ~CHN_STEREO;
631 	}
632 	song_unlock_audio();
633 }
634