ft2-clone

Fasttracker 2 clone
Log | Files | Refs | README | LICENSE

ft2_smpfx.c (29377B)


      1 // for finding memory leaks in debug mode with Visual Studio
      2 #if defined _DEBUG && defined _MSC_VER
      3 #include <crtdbg.h>
      4 #endif
      5 
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 #include <stdint.h>
      9 #include <stdbool.h>
     10 #include <math.h>
     11 #include "ft2_header.h"
     12 #include "ft2_audio.h"
     13 #include "ft2_pattern_ed.h"
     14 #include "ft2_gui.h"
     15 #include "ft2_sample_ed.h"
     16 #include "ft2_structs.h"
     17 #include "ft2_replayer.h"
     18 
     19 #define RESONANCE_RANGE 99
     20 #define RESONANCE_MIN 0.01 /* prevent massive blow-up */
     21 
     22 enum
     23 {
     24 	REMOVE_SAMPLE_MARK = 0,
     25 	KEEP_SAMPLE_MARK   = 1
     26 };
     27 
     28 static struct
     29 {
     30 	bool filled, keepSampleMark;
     31 	uint8_t flags, undoInstr, undoSmp;
     32 	uint32_t length, loopStart, loopLength;
     33 	int8_t *smpData8;
     34 	int16_t *smpData16;
     35 } sampleUndo;
     36 
     37 typedef struct
     38 {
     39 	double a1, a2, a3, b1, b2;
     40 	double inTmp[2], outTmp[2];
     41 } resoFilter_t;
     42 
     43 enum
     44 {
     45 	FILTER_LOWPASS  = 0,
     46 	FILTER_HIGHPASS = 1
     47 };
     48 
     49 static bool normalization;
     50 static uint8_t lastFilterType;
     51 static int32_t lastLpCutoff = 2000, lastHpCutoff = 200, filterResonance, smpCycles = 1, lastWaveLength = 64, lastAmp = 75;
     52 
     53 void clearSampleUndo(void)
     54 {
     55 	if (sampleUndo.smpData8 != NULL)
     56 	{
     57 		free(sampleUndo.smpData8);
     58 		sampleUndo.smpData8 = NULL;
     59 	}
     60 
     61 	if (sampleUndo.smpData16 != NULL)
     62 	{
     63 		free(sampleUndo.smpData16);
     64 		sampleUndo.smpData16 = NULL;
     65 	}
     66 
     67 	sampleUndo.filled = false;
     68 	sampleUndo.keepSampleMark = false;
     69 }
     70 
     71 static void fillSampleUndo(bool keepSampleMark)
     72 {
     73 	sampleUndo.filled = false;
     74 
     75 	sample_t *s = getCurSample();
     76 	if (s != NULL && s->length > 0)
     77 	{
     78 		pauseAudio();
     79 		unfixSample(s);
     80 
     81 		clearSampleUndo();
     82 
     83 		sampleUndo.undoInstr = editor.curInstr;
     84 		sampleUndo.undoSmp = editor.curSmp;
     85 		sampleUndo.flags = s->flags;
     86 		sampleUndo.length = s->length;
     87 		sampleUndo.loopStart = s->loopStart;
     88 		sampleUndo.loopLength = s->loopLength;
     89 		sampleUndo.keepSampleMark = keepSampleMark;
     90 
     91 		if (s->flags & SAMPLE_16BIT)
     92 		{
     93 			sampleUndo.smpData16 = (int16_t *)malloc(s->length * sizeof (int16_t));
     94 			if (sampleUndo.smpData16 != NULL)
     95 			{
     96 				memcpy(sampleUndo.smpData16, s->dataPtr, s->length * sizeof (int16_t));
     97 				sampleUndo.filled = true;
     98 			}
     99 		}
    100 		else
    101 		{
    102 			sampleUndo.smpData8 = (int8_t *)malloc(s->length * sizeof (int8_t));
    103 			if (sampleUndo.smpData8 != NULL)
    104 			{
    105 				memcpy(sampleUndo.smpData8, s->dataPtr, s->length * sizeof (int8_t));
    106 				sampleUndo.filled = true;
    107 			}
    108 		}
    109 
    110 		fixSample(s);
    111 		resumeAudio();
    112 	}
    113 }
    114 
    115 static sample_t *setupNewSample(uint32_t length)
    116 {
    117 	pauseAudio();
    118 
    119 	if (instr[editor.curInstr] == NULL)
    120 		allocateInstr(editor.curInstr);
    121 
    122 	if (instr[editor.curInstr] == NULL)
    123 		goto Error;
    124 
    125 	sample_t *s = &instr[editor.curInstr]->smp[editor.curSmp];
    126 
    127 	if (!reallocateSmpData(s, length, true))
    128 		goto Error;
    129 
    130 	s->isFixed = false;
    131 	s->length = length;
    132 	s->loopLength = s->loopStart = 0;
    133 	s->flags = SAMPLE_16BIT;
    134 
    135 	resumeAudio();
    136 	return s;
    137 
    138 Error:
    139 	resumeAudio();
    140 	return NULL;
    141 }
    142 
    143 void cbSfxNormalization(void)
    144 {
    145 	normalization ^= 1;
    146 }
    147 
    148 static void drawSampleCycles(void)
    149 {
    150 	const int16_t x = 54;
    151 
    152 	fillRect(x, 352, 7*3, 8, PAL_DESKTOP);
    153 
    154 	char str[16];
    155 	sprintf(str, "%03d", smpCycles);
    156 	textOut(x, 352, PAL_FORGRND, str);
    157 }
    158 
    159 void pbSfxCyclesUp(void)
    160 {
    161 	if (smpCycles < 256)
    162 	{
    163 		smpCycles++;
    164 		drawSampleCycles();
    165 	}
    166 }
    167 
    168 void pbSfxCyclesDown(void)
    169 {
    170 	if (smpCycles > 1)
    171 	{
    172 		smpCycles--;
    173 		drawSampleCycles();
    174 	}
    175 }
    176 
    177 void pbSfxTriangle(void)
    178 {
    179 	char lengthStr[5+1];
    180 	memset(lengthStr, '\0', sizeof (lengthStr));
    181 	snprintf(lengthStr, sizeof (lengthStr), "%d", lastWaveLength);
    182 
    183 	if (inputBox(1, "Enter new waveform length:", lengthStr, sizeof (lengthStr)-1) != 1)
    184 		return;
    185 
    186 	if (lengthStr[0] == '\0')
    187 		return;
    188 
    189 	lastWaveLength = (int32_t)atoi(lengthStr);
    190 	if (lastWaveLength <= 1 || lastWaveLength > 65536)
    191 	{
    192 		okBox(0, "System message", "Illegal range! Allowed range is 2..65535", NULL);
    193 		return;
    194 	}
    195 
    196 	fillSampleUndo(REMOVE_SAMPLE_MARK);
    197 	
    198 	int32_t newLength = lastWaveLength * smpCycles;
    199 
    200 	pauseAudio();
    201 
    202 	sample_t *s = setupNewSample(newLength);
    203 	if (s == NULL)
    204 	{
    205 		resumeAudio();
    206 		okBox(0, "System message", "Not enough memory!", NULL);
    207 		return;
    208 	}
    209 
    210 	const double delta = 4.0 / lastWaveLength;
    211 	double phase = 0.0;
    212 
    213 	int16_t *ptr16 = (int16_t *)s->dataPtr;
    214 	for (int32_t i = 0; i < newLength; i++)
    215 	{
    216 		double t = phase;
    217 		if (t > 3.0)
    218 			t -= 4.0;
    219 		else if (t >= 1.0)
    220 			t = 2.0 - t;
    221 
    222 		*ptr16++ = (int16_t)(t * INT16_MAX);
    223 		phase = fmod(phase + delta, 4.0);
    224 	}
    225 
    226 	s->loopLength = newLength;
    227 	s->flags |= LOOP_FORWARD;
    228 	fixSample(s);
    229 	resumeAudio();
    230 
    231 	updateSampleEditorSample();
    232 }
    233 
    234 void pbSfxSaw(void)
    235 {
    236 	char lengthStr[5+1];
    237 	memset(lengthStr, '\0', sizeof (lengthStr));
    238 	snprintf(lengthStr, sizeof (lengthStr), "%d", lastWaveLength);
    239 
    240 	if (inputBox(1, "Enter new waveform length:", lengthStr, sizeof (lengthStr)-1) != 1)
    241 		return;
    242 
    243 	if (lengthStr[0] == '\0')
    244 		return;
    245 
    246 	lastWaveLength = (int32_t)atoi(lengthStr);
    247 	if (lastWaveLength <= 1 || lastWaveLength > 65536)
    248 	{
    249 		okBox(0, "System message", "Illegal range! Allowed range is 2..65535", NULL);
    250 		return;
    251 	}
    252 
    253 	fillSampleUndo(REMOVE_SAMPLE_MARK);
    254 
    255 	int32_t newLength = lastWaveLength * smpCycles;
    256 
    257 	pauseAudio();
    258 
    259 	sample_t *s = setupNewSample(newLength);
    260 	if (s == NULL)
    261 	{
    262 		resumeAudio();
    263 		okBox(0, "System message", "Not enough memory!", NULL);
    264 		return;
    265 	}
    266 
    267 	uint64_t point64 = 0;
    268 	uint64_t delta64 = ((uint64_t)(INT16_MAX*2) << 32ULL) / lastWaveLength;
    269 
    270 	int16_t *ptr16 = (int16_t *)s->dataPtr;
    271 	for (int32_t i = 0; i < newLength; i++)
    272 	{
    273 		*ptr16++ = (int16_t)(point64 >> 32);
    274 		point64 += delta64;
    275 	}
    276 
    277 	s->loopLength = newLength;
    278 	s->flags |= LOOP_FORWARD;
    279 	fixSample(s);
    280 	resumeAudio();
    281 
    282 	updateSampleEditorSample();
    283 }
    284 
    285 void pbSfxSine(void)
    286 {
    287 	char lengthStr[5+1];
    288 	memset(lengthStr, '\0', sizeof (lengthStr));
    289 	snprintf(lengthStr, sizeof (lengthStr), "%d", lastWaveLength);
    290 
    291 	if (inputBox(1, "Enter new waveform length:", lengthStr, sizeof (lengthStr)-1) != 1)
    292 		return;
    293 
    294 	if (lengthStr[0] == '\0')
    295 		return;
    296 
    297 	lastWaveLength = (int32_t)atoi(lengthStr);
    298 	if (lastWaveLength <= 1 || lastWaveLength > 65536)
    299 	{
    300 		okBox(0, "System message", "Illegal range! Allowed range is 2..65535", NULL);
    301 		return;
    302 	}
    303 
    304 	fillSampleUndo(REMOVE_SAMPLE_MARK);
    305 
    306 	int32_t newLength = lastWaveLength * smpCycles;
    307 
    308 	pauseAudio();
    309 
    310 	sample_t *s = setupNewSample(newLength);
    311 	if (s == NULL)
    312 	{
    313 		resumeAudio();
    314 		okBox(0, "System message", "Not enough memory!", NULL);
    315 		return;
    316 	}
    317 
    318 	const double dMul = (2.0 * M_PI) / lastWaveLength;
    319 
    320 	int16_t *ptr16 = (int16_t *)s->dataPtr;
    321 	for (int32_t i = 0; i < newLength; i++)
    322 		*ptr16++ = (int16_t)(INT16_MAX * sin(i * dMul));
    323 
    324 	s->loopLength = newLength;
    325 	s->flags |= LOOP_FORWARD;
    326 	fixSample(s);
    327 	resumeAudio();
    328 
    329 	updateSampleEditorSample();
    330 }
    331 
    332 void pbSfxSquare(void)
    333 {
    334 	char lengthStr[5+1];
    335 	memset(lengthStr, '\0', sizeof (lengthStr));
    336 	snprintf(lengthStr, sizeof (lengthStr), "%d", lastWaveLength);
    337 
    338 	if (inputBox(1, "Enter new waveform length:", lengthStr, sizeof (lengthStr)-1) != 1)
    339 		return;
    340 
    341 	if (lengthStr[0] == '\0')
    342 		return;
    343 
    344 	lastWaveLength = (int32_t)atoi(lengthStr);
    345 	if (lastWaveLength <= 1 || lastWaveLength > 65536)
    346 	{
    347 		okBox(0, "System message", "Illegal range! Allowed range is 2..65535", NULL);
    348 		return;
    349 	}
    350 
    351 	fillSampleUndo(REMOVE_SAMPLE_MARK);
    352 
    353 	uint32_t newLength = lastWaveLength * smpCycles;
    354 
    355 	pauseAudio();
    356 
    357 	sample_t *s = setupNewSample(newLength);
    358 	if (s == NULL)
    359 	{
    360 		resumeAudio();
    361 		okBox(0, "System message", "Not enough memory!", NULL);
    362 		return;
    363 	}
    364 
    365 	const uint32_t halfWaveLength = lastWaveLength / 2;
    366 
    367 	int16_t currValue = INT16_MAX;
    368 	uint32_t counter = 0;
    369 
    370 	int16_t *ptr16 = (int16_t *)s->dataPtr;
    371 	for (uint32_t i = 0; i < newLength; i++)
    372 	{
    373 		*ptr16++ = currValue;
    374 		if (++counter >= halfWaveLength)
    375 		{
    376 			counter = 0;
    377 			currValue = -currValue;
    378 		}
    379 	}
    380 
    381 	s->loopLength = newLength;
    382 	s->flags |= LOOP_FORWARD;
    383 	fixSample(s);
    384 	resumeAudio();
    385 
    386 	updateSampleEditorSample();
    387 }
    388 
    389 void drawFilterResonance(void)
    390 {
    391 	const int16_t x = 172;
    392 
    393 	fillRect(x, 352, 18, 12, PAL_DESKTOP);
    394 
    395 	if (filterResonance <= 0)
    396 	{
    397 		textOut(x, 352, PAL_FORGRND, "off");
    398 	}
    399 	else
    400 	{
    401 		char str[16];
    402 		sprintf(str, "%02d", filterResonance);
    403 		textOut(x+3, 352, PAL_FORGRND, str);
    404 	}
    405 }
    406 
    407 void pbSfxResoUp(void)
    408 {
    409 	if (filterResonance < RESONANCE_RANGE)
    410 	{
    411 		filterResonance++;
    412 		drawFilterResonance();
    413 	}
    414 }
    415 
    416 void pbSfxResoDown(void)
    417 {
    418 	if (filterResonance > 0)
    419 	{
    420 		filterResonance--;
    421 		drawFilterResonance();
    422 	}
    423 }
    424 
    425 #define CUTOFF_EPSILON (1E-4)
    426 
    427 static void setupResoLpFilter(sample_t *s, resoFilter_t *f, double cutoff, uint32_t resonance, bool absoluteCutoff)
    428 {
    429 	// 12dB/oct resonant low-pass filter
    430 
    431 	if (!absoluteCutoff)
    432 	{
    433 		const double sampleFreq = getSampleC4Rate(s);
    434 		if (cutoff >= sampleFreq/2.0)
    435 			cutoff = (sampleFreq/2.0) - CUTOFF_EPSILON;
    436 
    437 		cutoff /= sampleFreq;
    438 	}
    439 
    440 	double r = sqrt(2.0);
    441 	if (resonance > 0)
    442 	{
    443 		r = pow(10.0, (resonance * -24.0) / (RESONANCE_RANGE * 20.0));
    444 		if (r < RESONANCE_MIN)
    445 			r = RESONANCE_MIN;
    446 	}
    447 
    448 	const double c = 1.0 / tan(PI * cutoff);
    449 
    450 	f->a1 = 1.0 / (1.0 + r * c + c * c);
    451 	f->a2 = 2.0 * f->a1;
    452 	f->a3 = f->a1;
    453 	f->b1 = 2.0 * (1.0 - c*c) * f->a1;
    454 	f->b2 = (1.0 - r * c + c * c) * f->a1;
    455 
    456 	f->inTmp[0] = f->inTmp[1] = f->outTmp[0] = f->outTmp[1] = 0.0; // clear filter history
    457 }
    458 
    459 static void setupResoHpFilter(sample_t *s, resoFilter_t *f, double cutoff, uint32_t resonance, bool absoluteCutoff)
    460 {
    461 	// 12dB/oct resonant high-pass filter
    462 
    463 	if (!absoluteCutoff)
    464 	{
    465 		const double sampleFreq = getSampleC4Rate(s);
    466 		if (cutoff >= sampleFreq/2.0)
    467 			cutoff = (sampleFreq/2.0) - CUTOFF_EPSILON;
    468 
    469 		cutoff /= sampleFreq;
    470 	}
    471 
    472 	double r = sqrt(2.0);
    473 	if (resonance > 0)
    474 	{
    475 		r = pow(10.0, (resonance * -24.0) / (RESONANCE_RANGE * 20.0));
    476 		if (r < RESONANCE_MIN)
    477 			r = RESONANCE_MIN;
    478 	}
    479 
    480 	const double c = tan(PI * cutoff);
    481 
    482 	f->a1 = 1.0 / (1.0 + r * c + c * c);
    483 	f->a2 = -2.0 * f->a1;
    484 	f->a3 = f->a1;
    485 	f->b1 = 2.0 * (c*c - 1.0) * f->a1;
    486 	f->b2 = (1.0 - r * c + c * c) * f->a1;
    487 
    488 	f->inTmp[0] = f->inTmp[1] = f->outTmp[0] = f->outTmp[1] = 0.0; // clear filter history
    489 }
    490 
    491 static bool applyResoFilter(sample_t *s, resoFilter_t *f)
    492 {
    493 	int32_t x1, x2;
    494 	if (smpEd_Rx1 < smpEd_Rx2)
    495 	{
    496 		x1 = smpEd_Rx1;
    497 		x2 = smpEd_Rx2;
    498 
    499 		if (x2 > s->length)
    500 			x2 = s->length;
    501 
    502 		if (x1 < 0)
    503 			x1 = 0;
    504 
    505 		if (x2 <= x1)
    506 			return true;
    507 	}
    508 	else
    509 	{
    510 		// no mark, operate on whole sample
    511 		x1 = 0;
    512 		x2 = s->length;
    513 	}
    514 	
    515 	const int32_t len = x2 - x1;
    516 
    517 	if (!normalization)
    518 	{
    519 		pauseAudio();
    520 		unfixSample(s);
    521 
    522 		if (s->flags & SAMPLE_16BIT)
    523 		{
    524 			int16_t *ptr16 = (int16_t *)s->dataPtr + x1;
    525 			for (int32_t i = 0; i < len; i++)
    526 			{
    527 				double out = (f->a1*ptr16[i]) + (f->a2*f->inTmp[0]) + (f->a3*f->inTmp[1]) - (f->b1*f->outTmp[0]) - (f->b2*f->outTmp[1]);
    528 
    529 				f->inTmp[1] = f->inTmp[0];
    530 				f->inTmp[0] = ptr16[i];
    531 
    532 				f->outTmp[1] = f->outTmp[0];
    533 				f->outTmp[0] = out;
    534 
    535 				ptr16[i] = (int16_t)CLAMP(out, INT16_MIN, INT16_MAX);
    536 			}
    537 		}
    538 		else
    539 		{
    540 			int8_t *ptr8 = (int8_t *)s->dataPtr + x1;
    541 			for (int32_t i = 0; i < len; i++)
    542 			{
    543 				double out = (f->a1*ptr8[i]) + (f->a2*f->inTmp[0]) + (f->a3*f->inTmp[1]) - (f->b1*f->outTmp[0]) - (f->b2*f->outTmp[1]);
    544 
    545 				f->inTmp[1] = f->inTmp[0];
    546 				f->inTmp[0] = ptr8[i];
    547 
    548 				f->outTmp[1] = f->outTmp[0];
    549 				f->outTmp[0] = out;
    550 
    551 				ptr8[i] = (int8_t)CLAMP(out, INT8_MIN, INT8_MAX);
    552 			}
    553 		}
    554 
    555 		fixSample(s);
    556 		resumeAudio();
    557 	}
    558 	else // normalize peak, no clipping
    559 	{
    560 		double *dSmp = (double *)malloc(len * sizeof (double));
    561 		if (dSmp == NULL)
    562 		{
    563 			okBox(0, "System message", "Not enough memory!", NULL);
    564 			return false;
    565 		}
    566 
    567 		pauseAudio();
    568 		unfixSample(s);
    569 
    570 		if (s->flags & SAMPLE_16BIT)
    571 		{
    572 			int16_t *ptr16 = (int16_t *)s->dataPtr + x1;
    573 			for (int32_t i = 0; i < len; i++)
    574 				dSmp[i] = (double)ptr16[i];
    575 		}
    576 		else
    577 		{
    578 			int8_t *ptr8 = (int8_t *)s->dataPtr + x1;
    579 			for (int32_t i = 0; i < len; i++)
    580 				dSmp[i] = (double)ptr8[i];
    581 		}
    582 
    583 		double peak = 0.0;
    584 		for (int32_t i = 0; i < len; i++)
    585 		{
    586 			const double out = (f->a1*dSmp[i]) + (f->a2*f->inTmp[0]) + (f->a3*f->inTmp[1]) - (f->b1*f->outTmp[0]) - (f->b2*f->outTmp[1]);
    587 
    588 			f->inTmp[1] = f->inTmp[0];
    589 			f->inTmp[0] = dSmp[i];
    590 
    591 			f->outTmp[1] = f->outTmp[0];
    592 			f->outTmp[0] = out;
    593 
    594 			dSmp[i] = out;
    595 
    596 			const double outAbs = fabs(out);
    597 			if (outAbs > peak)
    598 				peak = outAbs;
    599 		}
    600 
    601 		if (s->flags & SAMPLE_16BIT)
    602 		{
    603 			const double scale = INT16_MAX / peak;
    604 
    605 			int16_t *ptr16 = (int16_t *)s->dataPtr + x1;
    606 			for (int32_t i = 0; i < len; i++)
    607 				ptr16[i] = (int16_t)(dSmp[i] * scale);
    608 		}
    609 		else
    610 		{
    611 			const double scale = INT8_MAX / peak;
    612 
    613 			int8_t *ptr8 = (int8_t *)s->dataPtr + x1;
    614 			for (int32_t i = 0; i < len; i++)
    615 				ptr8[i] = (int8_t)(dSmp[i] * scale);
    616 		}
    617 
    618 		free(dSmp);
    619 
    620 		fixSample(s);
    621 		resumeAudio();
    622 	}
    623 
    624 	return true;
    625 }
    626 
    627 void pbSfxLowPass(void)
    628 {
    629 	resoFilter_t f;
    630 
    631 	sample_t *s = getCurSample();
    632 	if (s == NULL || s->dataPtr == NULL)
    633 		return;
    634 
    635 	char lengthStr[5+1];
    636 	memset(lengthStr, '\0', sizeof (lengthStr));
    637 	snprintf(lengthStr, sizeof (lengthStr), "%d", lastLpCutoff);
    638 
    639 	lastFilterType = FILTER_LOWPASS;
    640 	if (inputBox(6, "Enter low-pass filter cutoff (in Hz):", lengthStr, sizeof (lengthStr)-1) != 1)
    641 		return;
    642 
    643 	if (lengthStr[0] == '\0')
    644 		return;
    645 
    646 	lastLpCutoff = (int32_t)atoi(lengthStr);
    647 	if (lastLpCutoff < 1 || lastLpCutoff > 99999)
    648 	{
    649 		okBox(0, "System message", "Illegal range! Allowed range is 1..99999", NULL);
    650 		return;
    651 	}
    652 
    653 	setupResoLpFilter(s, &f, lastLpCutoff, filterResonance, false);
    654 	fillSampleUndo(KEEP_SAMPLE_MARK);
    655 	applyResoFilter(s, &f);
    656 	writeSample(true);
    657 }
    658 
    659 void pbSfxHighPass(void)
    660 {
    661 	resoFilter_t f;
    662 
    663 	sample_t *s = getCurSample();
    664 	if (s == NULL || s->dataPtr == NULL)
    665 		return;
    666 
    667 	char lengthStr[5+1];
    668 	memset(lengthStr, '\0', sizeof (lengthStr));
    669 	snprintf(lengthStr, sizeof (lengthStr), "%d", lastHpCutoff);
    670 
    671 	lastFilterType = FILTER_HIGHPASS;
    672 	if (inputBox(6, "Enter high-pass filter cutoff (in Hz):", lengthStr, sizeof (lengthStr)-1) != 1)
    673 		return;
    674 
    675 	if (lengthStr[0] == '\0')
    676 		return;
    677 
    678 	lastHpCutoff = (int32_t)atoi(lengthStr);
    679 	if (lastHpCutoff < 1 || lastHpCutoff > 99999)
    680 	{
    681 		okBox(0, "System message", "Illegal range! Allowed range is 1..99999", NULL);
    682 		return;
    683 	}
    684 
    685 	setupResoHpFilter(s, &f, lastHpCutoff, filterResonance, false);
    686 	fillSampleUndo(KEEP_SAMPLE_MARK);
    687 	applyResoFilter(s, &f);
    688 	writeSample(true);
    689 }
    690 
    691 void sfxPreviewFilter(uint32_t cutoff)
    692 {
    693 	sample_t oldSample;
    694 	resoFilter_t f;
    695 
    696 	sample_t *s = getCurSample();
    697 	if (s == NULL || s->dataPtr == NULL || s->length == 0 || cutoff < 1 || cutoff > 99999)
    698 		return;
    699 
    700 	int32_t x1, x2;
    701 	if (smpEd_Rx1 < smpEd_Rx2)
    702 	{
    703 		x1 = smpEd_Rx1;
    704 		x2 = smpEd_Rx2;
    705 
    706 		if (x2 > s->length)
    707 			x2 = s->length;
    708 
    709 		if (x1 < 0)
    710 			x1 = 0;
    711 
    712 		if (x2 <= x1)
    713 			return;
    714 	}
    715 	else
    716 	{
    717 		// no mark, operate on whole sample
    718 		x1 = 0;
    719 		x2 = s->length;
    720 	}
    721 
    722 	const int32_t len = x2 - x1;
    723 
    724 	pauseAudio();
    725 	unfixSample(s);
    726 	memcpy(&oldSample, s, sizeof (sample_t));
    727 
    728 	if (lastFilterType == FILTER_LOWPASS)
    729 		setupResoLpFilter(s, &f, cutoff, filterResonance, false);
    730 	else
    731 		setupResoHpFilter(s, &f, cutoff, filterResonance, false);
    732 
    733 	// prepare new sample
    734 	int8_t *sampleData;
    735 	if (s->flags & SAMPLE_16BIT)
    736 	{
    737 		sampleData = (int8_t *)malloc((len * sizeof (int16_t)) + SAMPLE_PAD_LENGTH);
    738 		if (sampleData == NULL)
    739 			goto Error;
    740 
    741 		memcpy(sampleData + SMP_DAT_OFFSET, (int16_t *)s->dataPtr + x1, len * sizeof (int16_t));
    742 	}
    743 	else
    744 	{
    745 		sampleData = (int8_t *)malloc((len * sizeof (int8_t)) + SAMPLE_PAD_LENGTH);
    746 		if (sampleData == NULL)
    747 			goto Error;
    748 
    749 		memcpy(sampleData + SMP_DAT_OFFSET, (int8_t *)s->dataPtr + x1, len * sizeof (int8_t));
    750 	}
    751 
    752 	s->origDataPtr = sampleData;
    753 	s->length = len;
    754 	s->dataPtr = s->origDataPtr + SMP_DAT_OFFSET;
    755 	s->loopStart = s->loopLength = 0;
    756 	fixSample(s);
    757 
    758 	const int32_t oldX1 = smpEd_Rx1;
    759 	const int32_t oldX2 = smpEd_Rx2;
    760 	smpEd_Rx1 = smpEd_Rx2 = 0;
    761 	applyResoFilter(s, &f);
    762 	smpEd_Rx1 = oldX1;
    763 	smpEd_Rx2 = oldX2;
    764 
    765 	// set up preview sample on channel 0
    766 	channel_t *ch = &channel[0];
    767 	uint8_t note = editor.smpEd_NoteNr;
    768 	ch->smpNum = editor.curSmp;
    769 	ch->instrNum = editor.curInstr;
    770 	ch->copyOfInstrAndNote = (ch->instrNum << 8) | note;
    771 	ch->efx = 0;
    772 	ch->smpStartPos = 0;
    773 	resumeAudio();
    774 	triggerNote(note, 0, 0, ch);
    775 	resetVolumes(ch);
    776 	triggerInstrument(ch);
    777 	ch->realVol = ch->outVol = ch->oldVol = 64;
    778 	updateVolPanAutoVib(ch);
    779 
    780 	while (ch->status & IS_Trigger); // wait for sample to latch in mixer
    781 	SDL_Delay(1500); // wait 1.5 seconds
    782 
    783 	// we're done, stop voice and free temporary data
    784 	pauseAudio();
    785 	free(sampleData);
    786 
    787 Error:
    788 	// set back old sample
    789 	memcpy(s, &oldSample, sizeof (sample_t));
    790 	fixSample(s);
    791 	resumeAudio();
    792 }
    793 
    794 void pbSfxSubBass(void)
    795 {
    796 	resoFilter_t f;
    797 
    798 	sample_t *s = getCurSample();
    799 	if (s == NULL || s->dataPtr == NULL)
    800 		return;
    801 
    802 	setupResoHpFilter(s, &f, 0.001, 0, true);
    803 	fillSampleUndo(KEEP_SAMPLE_MARK);
    804 	applyResoFilter(s, &f);
    805 	writeSample(true);
    806 }
    807 
    808 void pbSfxAddBass(void)
    809 {
    810 	resoFilter_t f;
    811 
    812 	sample_t *s = getCurSample();
    813 	if (s == NULL || s->dataPtr == NULL)
    814 		return;
    815 
    816 	int32_t x1, x2;
    817 	if (smpEd_Rx1 < smpEd_Rx2)
    818 	{
    819 		x1 = smpEd_Rx1;
    820 		x2 = smpEd_Rx2;
    821 
    822 		if (x2 > s->length)
    823 			x2 = s->length;
    824 
    825 		if (x1 < 0)
    826 			x1 = 0;
    827 
    828 		if (x2 <= x1)
    829 			return;
    830 	}
    831 	else
    832 	{
    833 		// no mark, operate on whole sample
    834 		x1 = 0;
    835 		x2 = s->length;
    836 	}
    837 	
    838 	const int32_t len = x2 - x1;
    839 
    840 	setupResoLpFilter(s, &f, 0.015, 0, true);
    841 
    842 	double *dSmp = (double *)malloc(len * sizeof (double));
    843 	if (dSmp == NULL)
    844 	{
    845 		okBox(0, "System message", "Not enough memory!", NULL);
    846 		return;
    847 	}
    848 
    849 	fillSampleUndo(KEEP_SAMPLE_MARK);
    850 
    851 	pauseAudio();
    852 	unfixSample(s);
    853 
    854 	if (s->flags & SAMPLE_16BIT)
    855 	{
    856 		int16_t *ptr16 = (int16_t *)s->dataPtr + x1;
    857 		for (int32_t i = 0; i < len; i++)
    858 			dSmp[i] = (double)ptr16[i];
    859 	}
    860 	else
    861 	{
    862 		int8_t *ptr8 = (int8_t *)s->dataPtr + x1;
    863 		for (int32_t i = 0; i < len; i++)
    864 			dSmp[i] = (double)ptr8[i];
    865 	}
    866 
    867 	if (!normalization)
    868 	{
    869 		for (int32_t i = 0; i < len; i++)
    870 		{
    871 			double out = (f.a1*dSmp[i]) + (f.a2*f.inTmp[0]) + (f.a3*f.inTmp[1]) - (f.b1*f.outTmp[0]) - (f.b2*f.outTmp[1]);
    872 
    873 			f.inTmp[1] = f.inTmp[0];
    874 			f.inTmp[0] = dSmp[i];
    875 
    876 			f.outTmp[1] = f.outTmp[0];
    877 			f.outTmp[0] = out;
    878 
    879 			dSmp[i] = out;
    880 		}
    881 
    882 		if (s->flags & SAMPLE_16BIT)
    883 		{
    884 			int16_t *ptr16 = (int16_t *)s->dataPtr + x1;
    885 			for (int32_t i = 0; i < len; i++)
    886 			{
    887 				double out = ptr16[i] + (dSmp[i] * 0.25);
    888 				out = CLAMP(out, INT16_MIN, INT16_MAX);
    889 
    890 				ptr16[i] = (int16_t)out;
    891 			}
    892 		}
    893 		else
    894 		{
    895 			int8_t *ptr8 = (int8_t *)s->dataPtr + x1;
    896 			for (int32_t i = 0; i < len; i++)
    897 			{
    898 				double out = ptr8[i] + (dSmp[i] * 0.25);
    899 				out = CLAMP(out, INT8_MIN, INT8_MAX);
    900 
    901 				ptr8[i] = (int8_t)out;
    902 			}
    903 		}
    904 	}
    905 	else
    906 	{
    907 		if (s->flags & SAMPLE_16BIT)
    908 		{
    909 			int16_t *ptr16 = (int16_t *)s->dataPtr + x1;
    910 
    911 			double peak = 0.0;
    912 			for (int32_t i = 0; i < len; i++)
    913 			{
    914 				double out = (f.a1*dSmp[i]) + (f.a2*f.inTmp[0]) + (f.a3*f.inTmp[1]) - (f.b1*f.outTmp[0]) - (f.b2*f.outTmp[1]);
    915 
    916 				f.inTmp[1] = f.inTmp[0];
    917 				f.inTmp[0] = dSmp[i];
    918 
    919 				f.outTmp[1] = f.outTmp[0];
    920 				f.outTmp[0] = out;
    921 
    922 				dSmp[i] = out;
    923 				double bass = ptr16[i] + (out * 0.25);
    924 
    925 				const double outAbs = fabs(bass);
    926 				if (outAbs > peak)
    927 					peak = outAbs;
    928 			}
    929 
    930 			double scale = INT16_MAX / peak;
    931 			for (int32_t i = 0; i < len; i++)
    932 				ptr16[i] = (int16_t)((ptr16[i] + (dSmp[i] * 0.25)) * scale);
    933 		}
    934 		else
    935 		{
    936 			int8_t *ptr8 = (int8_t *)s->dataPtr + x1;
    937 
    938 			double peak = 0.0;
    939 			for (int32_t i = 0; i < len; i++)
    940 			{
    941 				double out = (f.a1*dSmp[i]) + (f.a2*f.inTmp[0]) + (f.a3*f.inTmp[1]) - (f.b1*f.outTmp[0]) - (f.b2*f.outTmp[1]);
    942 
    943 				f.inTmp[1] = f.inTmp[0];
    944 				f.inTmp[0] = dSmp[i];
    945 
    946 				f.outTmp[1] = f.outTmp[0];
    947 				f.outTmp[0] = out;
    948 
    949 				dSmp[i] = out;
    950 				double bass = ptr8[i] + (out * 0.25);
    951 
    952 				const double outAbs = fabs(bass);
    953 				if (outAbs > peak)
    954 					peak = outAbs;
    955 			}
    956 
    957 			double scale = INT8_MAX / peak;
    958 			for (int32_t i = 0; i < len; i++)
    959 				ptr8[i] = (int8_t)((ptr8[i] + (dSmp[i] * 0.25)) * scale);
    960 		}
    961 	}
    962 
    963 	free(dSmp);
    964 
    965 	fixSample(s);
    966 	resumeAudio();
    967 
    968 	writeSample(true);
    969 }
    970 
    971 void pbSfxSubTreble(void)
    972 {
    973 	resoFilter_t f;
    974 
    975 	sample_t *s = getCurSample();
    976 	if (s == NULL || s->dataPtr == NULL)
    977 		return;
    978 
    979 	setupResoLpFilter(s, &f, 0.33, 0, true);
    980 	fillSampleUndo(KEEP_SAMPLE_MARK);
    981 	applyResoFilter(s, &f);
    982 	writeSample(true);
    983 }
    984 
    985 void pbSfxAddTreble(void)
    986 {
    987 	resoFilter_t f;
    988 
    989 	sample_t *s = getCurSample();
    990 	if (s == NULL || s->dataPtr == NULL)
    991 		return;
    992 
    993 	int32_t x1, x2;
    994 	if (smpEd_Rx1 < smpEd_Rx2)
    995 	{
    996 		x1 = smpEd_Rx1;
    997 		x2 = smpEd_Rx2;
    998 
    999 		if (x2 > s->length)
   1000 			x2 = s->length;
   1001 
   1002 		if (x1 < 0)
   1003 			x1 = 0;
   1004 
   1005 		if (x2 <= x1)
   1006 			return;
   1007 	}
   1008 	else
   1009 	{
   1010 		// no mark, operate on whole sample
   1011 		x1 = 0;
   1012 		x2 = s->length;
   1013 	}
   1014 	
   1015 	const int32_t len = x2 - x1;
   1016 
   1017 	setupResoHpFilter(s, &f, 0.27, 0, true);
   1018 
   1019 	double *dSmp = (double *)malloc(len * sizeof (double));
   1020 	if (dSmp == NULL)
   1021 	{
   1022 		okBox(0, "System message", "Not enough memory!", NULL);
   1023 		return;
   1024 	}
   1025 
   1026 	fillSampleUndo(KEEP_SAMPLE_MARK);
   1027 
   1028 	pauseAudio();
   1029 	unfixSample(s);
   1030 
   1031 	if (s->flags & SAMPLE_16BIT)
   1032 	{
   1033 		int16_t *ptr16 = (int16_t *)s->dataPtr + x1;
   1034 		for (int32_t i = 0; i < len; i++)
   1035 			dSmp[i] = (double)ptr16[i];
   1036 	}
   1037 	else
   1038 	{
   1039 		int8_t *ptr8 = (int8_t *)s->dataPtr + x1;
   1040 		for (int32_t i = 0; i < len; i++)
   1041 			dSmp[i] = (double)ptr8[i];
   1042 	}
   1043 
   1044 	if (!normalization)
   1045 	{
   1046 		for (int32_t i = 0; i < len; i++)
   1047 		{
   1048 			double out = (f.a1*dSmp[i]) + (f.a2*f.inTmp[0]) + (f.a3*f.inTmp[1]) - (f.b1*f.outTmp[0]) - (f.b2*f.outTmp[1]);
   1049 
   1050 			f.inTmp[1] = f.inTmp[0];
   1051 			f.inTmp[0] = dSmp[i];
   1052 
   1053 			f.outTmp[1] = f.outTmp[0];
   1054 			f.outTmp[0] = out;
   1055 
   1056 			dSmp[i] = out;
   1057 		}
   1058 
   1059 		if (s->flags & SAMPLE_16BIT)
   1060 		{
   1061 			int16_t *ptr16 = (int16_t *)s->dataPtr + x1;
   1062 			for (int32_t i = 0; i < len; i++)
   1063 			{
   1064 				double out = ptr16[i] - (dSmp[i] * 0.25);
   1065 				out = CLAMP(out, INT16_MIN, INT16_MAX);
   1066 
   1067 				ptr16[i] = (int16_t)out;
   1068 			}
   1069 		}
   1070 		else
   1071 		{
   1072 			int8_t *ptr8 = (int8_t *)s->dataPtr + x1;
   1073 			for (int32_t i = 0; i < len; i++)
   1074 			{
   1075 				double out = ptr8[i] - (dSmp[i] * 0.25);
   1076 				out = CLAMP(out, INT8_MIN, INT8_MAX);
   1077 
   1078 				ptr8[i] = (int8_t)out;
   1079 			}
   1080 		}
   1081 	}
   1082 	else
   1083 	{
   1084 		if (s->flags & SAMPLE_16BIT)
   1085 		{
   1086 			int16_t *ptr16 = (int16_t *)s->dataPtr + x1;
   1087 
   1088 			double peak = 0.0;
   1089 			for (int32_t i = 0; i < len; i++)
   1090 			{
   1091 				double out = (f.a1*dSmp[i]) + (f.a2*f.inTmp[0]) + (f.a3*f.inTmp[1]) - (f.b1*f.outTmp[0]) - (f.b2*f.outTmp[1]);
   1092 
   1093 				f.inTmp[1] = f.inTmp[0];
   1094 				f.inTmp[0] = dSmp[i];
   1095 
   1096 				f.outTmp[1] = f.outTmp[0];
   1097 				f.outTmp[0] = out;
   1098 
   1099 				dSmp[i] = out;
   1100 				double treble = ptr16[i] - (out * 0.25);
   1101 
   1102 				const double outAbs = fabs(treble);
   1103 				if (outAbs > peak)
   1104 					peak = outAbs;
   1105 			}
   1106 
   1107 			double scale = INT16_MAX / peak;
   1108 			for (int32_t i = 0; i < len; i++)
   1109 				ptr16[i] = (int16_t)((ptr16[i] - (dSmp[i] * 0.25)) * scale);
   1110 		}
   1111 		else
   1112 		{
   1113 			int8_t *ptr8 = (int8_t *)s->dataPtr + x1;
   1114 
   1115 			double peak = 0.0;
   1116 			for (int32_t i = 0; i < len; i++)
   1117 			{
   1118 				double out = (f.a1*dSmp[i]) + (f.a2*f.inTmp[0]) + (f.a3*f.inTmp[1]) - (f.b1*f.outTmp[0]) - (f.b2*f.outTmp[1]);
   1119 
   1120 				f.inTmp[1] = f.inTmp[0];
   1121 				f.inTmp[0] = dSmp[i];
   1122 
   1123 				f.outTmp[1] = f.outTmp[0];
   1124 				f.outTmp[0] = out;
   1125 
   1126 				dSmp[i] = out;
   1127 				double treble = ptr8[i] - (out * 0.25);
   1128 
   1129 				const double outAbs = fabs(treble);
   1130 				if (outAbs > peak)
   1131 					peak = outAbs;
   1132 			}
   1133 
   1134 			double scale = INT8_MAX / peak;
   1135 			for (int32_t i = 0; i < len; i++)
   1136 				ptr8[i] = (int8_t)((ptr8[i] - (dSmp[i] * 0.25)) * scale);
   1137 		}
   1138 	}
   1139 
   1140 	free(dSmp);
   1141 
   1142 	fixSample(s);
   1143 	resumeAudio();
   1144 
   1145 	writeSample(true);
   1146 }
   1147 
   1148 void pbSfxSetAmp(void)
   1149 {
   1150 	sample_t *s = getCurSample();
   1151 	if (s == NULL || s->dataPtr == NULL)
   1152 		return;
   1153 
   1154 	int32_t x1, x2;
   1155 	if (smpEd_Rx1 < smpEd_Rx2)
   1156 	{
   1157 		x1 = smpEd_Rx1;
   1158 		x2 = smpEd_Rx2;
   1159 
   1160 		if (x2 > s->length)
   1161 			x2 = s->length;
   1162 
   1163 		if (x1 < 0)
   1164 			x1 = 0;
   1165 
   1166 		if (x2 <= x1)
   1167 			return;
   1168 	}
   1169 	else
   1170 	{
   1171 		// no mark, operate on whole sample
   1172 		x1 = 0;
   1173 		x2 = s->length;
   1174 	}
   1175 	
   1176 	const int32_t len = x2 - x1;
   1177 
   1178 	char ampStr[3+1];
   1179 	memset(ampStr, '\0', sizeof (ampStr));
   1180 	snprintf(ampStr, sizeof (ampStr), "%d", lastAmp);
   1181 
   1182 	if (inputBox(1, "Change sample amplitude (in percentage, 0..999):", ampStr, sizeof (ampStr)-1) != 1)
   1183 		return;
   1184 
   1185 	if (ampStr[0] == '\0')
   1186 		return;
   1187 
   1188 	lastAmp = (int32_t)atoi(ampStr);
   1189 
   1190 	fillSampleUndo(KEEP_SAMPLE_MARK);
   1191 
   1192 	pauseAudio();
   1193 	unfixSample(s);
   1194 
   1195 	const int32_t mul = (int32_t)round((1 << 22UL) * (lastAmp / 100.0));
   1196 
   1197 	if (s->flags & SAMPLE_16BIT)
   1198 	{
   1199 		int16_t *ptr16 = (int16_t *)s->dataPtr + x1;
   1200 		for (int32_t i = 0; i < len; i++)
   1201 		{
   1202 			int32_t sample = ((int64_t)ptr16[i] * (int32_t)mul) >> 22;
   1203 			sample = CLAMP(sample, INT16_MIN, INT16_MAX);
   1204 			ptr16[i] = (int16_t)sample;
   1205 		}
   1206 	}
   1207 	else
   1208 	{
   1209 		int8_t *ptr8 = (int8_t *)s->dataPtr + x1;
   1210 		for (int32_t i = 0; i < len; i++)
   1211 		{
   1212 			int32_t sample = ((int64_t)ptr8[i] * (int32_t)mul) >> 22;
   1213 			sample = CLAMP(sample, INT8_MIN, INT8_MAX);
   1214 			ptr8[i] = (int8_t)sample;
   1215 		}
   1216 	}
   1217 
   1218 	fixSample(s);
   1219 	resumeAudio();
   1220 
   1221 	writeSample(true);
   1222 }
   1223 
   1224 void pbSfxUndo(void)
   1225 {
   1226 	if (!sampleUndo.filled || sampleUndo.undoInstr != editor.curInstr || sampleUndo.undoSmp != editor.curSmp)
   1227 		return;
   1228 
   1229 	sample_t *s = getCurSample();
   1230 	if (s == NULL || s->dataPtr == NULL)
   1231 		return;
   1232 
   1233 	pauseAudio();
   1234 
   1235 	freeSmpData(s);
   1236 	s->flags = sampleUndo.flags;
   1237 	s->length = sampleUndo.length;
   1238 	s->loopStart = sampleUndo.loopStart;
   1239 	s->loopLength = sampleUndo.loopLength;
   1240 
   1241 	if (allocateSmpData(s, s->length, !!(s->flags & SAMPLE_16BIT)))
   1242 	{
   1243 		if (s->flags & SAMPLE_16BIT)
   1244 			memcpy(s->dataPtr, sampleUndo.smpData16, s->length * sizeof (int16_t));
   1245 		else
   1246 			memcpy(s->dataPtr, sampleUndo.smpData8, s->length * sizeof (int8_t));
   1247 
   1248 		fixSample(s);
   1249 		resumeAudio();
   1250 	}
   1251 	else
   1252 	{
   1253 		resumeAudio();
   1254 		okBox(0, "System message", "Not enough memory!", NULL);
   1255 	}
   1256 
   1257 	int32_t oldRx1 = smpEd_Rx1;
   1258 	int32_t oldRx2 = smpEd_Rx2;
   1259 
   1260 	updateSampleEditorSample();
   1261 
   1262 	if (sampleUndo.keepSampleMark && oldRx1 < oldRx2)
   1263 	{
   1264 		smpEd_Rx1 = oldRx1;
   1265 		smpEd_Rx2 = oldRx2;
   1266 		writeSample(false); // redraw sample mark only
   1267 	}
   1268 
   1269 	sampleUndo.keepSampleMark = false;
   1270 	sampleUndo.filled = false;
   1271 }
   1272 
   1273 void hideSampleEffectsScreen(void)
   1274 {
   1275 	ui.sampleEditorEffectsShown = false;
   1276 
   1277 	hideCheckBox(CB_SAMPFX_NORMALIZATION);
   1278 	hidePushButton(PB_SAMPFX_CYCLES_UP);
   1279 	hidePushButton(PB_SAMPFX_CYCLES_DOWN);
   1280 	hidePushButton(PB_SAMPFX_TRIANGLE);
   1281 	hidePushButton(PB_SAMPFX_SAW);
   1282 	hidePushButton(PB_SAMPFX_SINE);
   1283 	hidePushButton(PB_SAMPFX_SQUARE);
   1284 	hidePushButton(PB_SAMPFX_RESO_UP);
   1285 	hidePushButton(PB_SAMPFX_RESO_DOWN);
   1286 	hidePushButton(PB_SAMPFX_LOWPASS);
   1287 	hidePushButton(PB_SAMPFX_HIGHPASS);
   1288 	hidePushButton(PB_SAMPFX_SUB_BASS);
   1289 	hidePushButton(PB_SAMPFX_SUB_TREBLE);
   1290 	hidePushButton(PB_SAMPFX_ADD_BASS);
   1291 	hidePushButton(PB_SAMPFX_ADD_TREBLE);
   1292 	hidePushButton(PB_SAMPFX_SET_AMP);
   1293 	hidePushButton(PB_SAMPFX_UNDO);
   1294 	hidePushButton(PB_SAMPFX_XFADE);
   1295 	hidePushButton(PB_SAMPFX_BACK);
   1296 
   1297 	drawFramework(0,   346, 115, 54, FRAMEWORK_TYPE1);
   1298 	drawFramework(115, 346, 133, 54, FRAMEWORK_TYPE1);
   1299 	drawFramework(248, 346,  49, 54, FRAMEWORK_TYPE1);
   1300 	drawFramework(297, 346,  56, 54, FRAMEWORK_TYPE1);
   1301 
   1302 	showPushButton(PB_SAMP_PNOTE_UP);
   1303 	showPushButton(PB_SAMP_PNOTE_DOWN);
   1304 	showPushButton(PB_SAMP_STOP);
   1305 	showPushButton(PB_SAMP_PWAVE);
   1306 	showPushButton(PB_SAMP_PRANGE);
   1307 	showPushButton(PB_SAMP_PDISPLAY);
   1308 	showPushButton(PB_SAMP_SHOW_RANGE);
   1309 	showPushButton(PB_SAMP_RANGE_ALL);
   1310 	showPushButton(PB_SAMP_CLR_RANGE);
   1311 	showPushButton(PB_SAMP_ZOOM_OUT);
   1312 	showPushButton(PB_SAMP_SHOW_ALL);
   1313 	showPushButton(PB_SAMP_SAVE_RNG);
   1314 	showPushButton(PB_SAMP_CUT);
   1315 	showPushButton(PB_SAMP_COPY);
   1316 	showPushButton(PB_SAMP_PASTE);
   1317 	showPushButton(PB_SAMP_CROP);
   1318 	showPushButton(PB_SAMP_VOLUME);
   1319 	showPushButton(PB_SAMP_EFFECTS);
   1320 
   1321 	drawFramework(2, 366,  34, 15, FRAMEWORK_TYPE2);
   1322 	textOutShadow(5, 352, PAL_FORGRND, PAL_DSKTOP2, "Play:");
   1323 	updateSampleEditor();
   1324 }
   1325 
   1326 void pbEffects(void)
   1327 {
   1328 	hidePushButton(PB_SAMP_PNOTE_UP);
   1329 	hidePushButton(PB_SAMP_PNOTE_DOWN);
   1330 	hidePushButton(PB_SAMP_STOP);
   1331 	hidePushButton(PB_SAMP_PWAVE);
   1332 	hidePushButton(PB_SAMP_PRANGE);
   1333 	hidePushButton(PB_SAMP_PDISPLAY);
   1334 	hidePushButton(PB_SAMP_SHOW_RANGE);
   1335 	hidePushButton(PB_SAMP_RANGE_ALL);
   1336 	hidePushButton(PB_SAMP_CLR_RANGE);
   1337 	hidePushButton(PB_SAMP_ZOOM_OUT);
   1338 	hidePushButton(PB_SAMP_SHOW_ALL);
   1339 	hidePushButton(PB_SAMP_SAVE_RNG);
   1340 	hidePushButton(PB_SAMP_CUT);
   1341 	hidePushButton(PB_SAMP_COPY);
   1342 	hidePushButton(PB_SAMP_PASTE);
   1343 	hidePushButton(PB_SAMP_CROP);
   1344 	hidePushButton(PB_SAMP_VOLUME);
   1345 	hidePushButton(PB_SAMP_EFFECTS);
   1346 
   1347 	drawFramework(0,   346, 116, 54, FRAMEWORK_TYPE1);
   1348 	drawFramework(116, 346, 114, 54, FRAMEWORK_TYPE1);
   1349 	drawFramework(230, 346,  67, 54, FRAMEWORK_TYPE1);
   1350 	drawFramework(297, 346,  56, 54, FRAMEWORK_TYPE1);
   1351 
   1352 	checkBoxes[CB_SAMPFX_NORMALIZATION].checked = normalization ? true : false;
   1353 	showCheckBox(CB_SAMPFX_NORMALIZATION);
   1354 	showPushButton(PB_SAMPFX_CYCLES_UP);
   1355 	showPushButton(PB_SAMPFX_CYCLES_DOWN);
   1356 	showPushButton(PB_SAMPFX_TRIANGLE);
   1357 	showPushButton(PB_SAMPFX_SAW);
   1358 	showPushButton(PB_SAMPFX_SINE);
   1359 	showPushButton(PB_SAMPFX_SQUARE);
   1360 	showPushButton(PB_SAMPFX_RESO_UP);
   1361 	showPushButton(PB_SAMPFX_RESO_DOWN);
   1362 	showPushButton(PB_SAMPFX_LOWPASS);
   1363 	showPushButton(PB_SAMPFX_HIGHPASS);
   1364 	showPushButton(PB_SAMPFX_SUB_BASS);
   1365 	showPushButton(PB_SAMPFX_SUB_TREBLE);
   1366 	showPushButton(PB_SAMPFX_ADD_BASS);
   1367 	showPushButton(PB_SAMPFX_ADD_TREBLE);
   1368 	showPushButton(PB_SAMPFX_SET_AMP);
   1369 	showPushButton(PB_SAMPFX_UNDO);
   1370 	showPushButton(PB_SAMPFX_XFADE);
   1371 	showPushButton(PB_SAMPFX_BACK);
   1372 
   1373 	textOutShadow(4,   352, PAL_FORGRND, PAL_DSKTOP2, "Cycles:");
   1374 	drawSampleCycles();
   1375 
   1376 	textOutShadow(121, 352, PAL_FORGRND, PAL_DSKTOP2, "Reson.:");
   1377 	drawFilterResonance();
   1378 
   1379 	textOutShadow(135, 386, PAL_FORGRND, PAL_DSKTOP2, "Normalization");
   1380 
   1381 	textOutShadow(235, 352, PAL_FORGRND, PAL_DSKTOP2, "Bass");
   1382 	textOutShadow(235, 369, PAL_FORGRND, PAL_DSKTOP2, "Treb.");
   1383 
   1384 	ui.sampleEditorEffectsShown = true;
   1385 }