1664 lines · 33.0 KB · C
RawDownload
/* This file contains the routines for the following sample editor functions:** - Resampler** - Echo** - Mix** - Volume**/ // for finding memory leaks in debug mode with Visual Studio#if defined _DEBUG && defined _MSC_VER#include <crtdbg.h>#endif #include <stdio.h>#include <stdint.h>#include <stdbool.h>#include <math.h>#include "ft2_header.h"#include "ft2_mouse.h"#include "ft2_audio.h"#include "ft2_gui.h"#include "ft2_events.h"#include "ft2_video.h"#include "ft2_inst_ed.h"#include "ft2_sample_ed.h"#include "ft2_keyboard.h"#include "ft2_tables.h"#include "ft2_structs.h" static volatile bool stopThread; static int8_t smpEd_RelReSmp, mix_Balance = 50;static bool echo_AddMemory, exitFlag, outOfMemory;static int16_t echo_nEcho = 1, echo_VolChange = 30;static int32_t echo_Distance = 0x100;static double dVol_StartVol = 100.0, dVol_EndVol = 100.0;static SDL_Thread *thread; static void pbExit(void){	ui.sysReqShown = false;	exitFlag = true;} static void windowOpen(void){	ui.sysReqShown = true;	ui.sysReqEnterPressed = false; 	unstuckLastUsedGUIElement();	SDL_EventState(SDL_DROPFILE, SDL_DISABLE);} static void windowClose(bool rewriteSample){	SDL_EventState(SDL_DROPFILE, SDL_ENABLE); 	if (exitFlag || rewriteSample)		writeSample(true);	else		updateNewSample(); 	mouseAnimOff();} static void sbSetResampleTones(uint32_t pos){	if (smpEd_RelReSmp != (int8_t)(pos - 36))		smpEd_RelReSmp = (int8_t)(pos - 36);} static void pbResampleTonesDown(void){	if (smpEd_RelReSmp > -36)		smpEd_RelReSmp--;} static void pbResampleTonesUp(void){	if (smpEd_RelReSmp < 36)		smpEd_RelReSmp++;} static int32_t SDLCALL resampleThread(void *ptr){	smpPtr_t sp; 	if (instr[editor.curInstr] == NULL)		return true; 	sample_t *s = &instr[editor.curInstr]->smp[editor.curSmp];	bool sample16Bit = !!(s->flags & SAMPLE_16BIT); 	const double dRatio = exp2((int32_t)smpEd_RelReSmp / 12.0); 	double dNewLen = s->length * dRatio;	if (dNewLen > (double)MAX_SAMPLE_LEN)		dNewLen = (double)MAX_SAMPLE_LEN; 	const uint32_t newLen = (int32_t)floor(dNewLen);	if (!allocateSmpDataPtr(&sp, newLen, sample16Bit))	{		outOfMemory = true;		setMouseBusy(false);		ui.sysReqShown = false;		return true;	} 	int8_t *dst = sp.ptr;	int8_t *src = s->dataPtr; 	// 32.32 fixed-point logic	const uint64_t delta64 = (const uint64_t)round((UINT32_MAX+1.0) / dRatio);	uint64_t posFrac64 = 0; 	pauseAudio();	unfixSample(s); 	/* Nearest-neighbor resampling (no interpolation).	**	** Could benefit from windowed-sinc interpolation,	** but it seems like some people prefer no resampling	** interpolation (like FT2).	*/ 	if (newLen > 0)	{		if (sample16Bit)		{			const int16_t *src16 = (const int16_t *)src;			int16_t *dst16 = (int16_t *)dst; 			for (uint32_t i = 0; i < newLen; i++)			{				const uint32_t position = posFrac64 >> 32;				dst16[i] = src16[position];				posFrac64 += delta64;			}		}		else // 8-bit		{			const int8_t *src8 = src;			int8_t *dst8 = dst; 			for (uint32_t i = 0; i < newLen; i++)			{				const uint32_t position = posFrac64 >> 32;				dst8[i] = src8[position];				posFrac64 += delta64;			}		}	} 	freeSmpData(s);	setSmpDataPtr(s, &sp); 	s->relativeNote += smpEd_RelReSmp;	s->length = newLen;	s->loopStart = (int32_t)(s->loopStart * dRatio);	s->loopLength = (int32_t)(s->loopLength * dRatio); 	sanitizeSample(s); 	fixSample(s);	resumeAudio(); 	setSongModifiedFlag();	setMouseBusy(false); 	ui.sysReqShown = false;	return true; 	(void)ptr;} static void pbDoResampling(void){	mouseAnimOn();	thread = SDL_CreateThread(resampleThread, NULL, NULL);	if (thread == NULL)	{		okBox(0, "System message", "Couldn't create thread!");		return;	} 	SDL_DetachThread(thread);} static void drawResampleBox(void){	char sign;	const int16_t x = 209;	const int16_t y = 230;	const int16_t w = 214;	const int16_t h = 54; 	// main fill	fillRect(x + 1, y + 1, w - 2, h - 2, PAL_BUTTONS); 	// outer border	vLine(x,         y,         h - 1, PAL_BUTTON1);	hLine(x + 1,     y,         w - 2, PAL_BUTTON1);	vLine(x + w - 1, y,         h,     PAL_BUTTON2);	hLine(x,         y + h - 1, w - 1, PAL_BUTTON2); 	// inner border	vLine(x + 2,     y + 2,     h - 5, PAL_BUTTON2);	hLine(x + 3,     y + 2,     w - 6, PAL_BUTTON2);	vLine(x + w - 3, y + 2,     h - 4, PAL_BUTTON1);	hLine(x + 2,     y + h - 3, w - 4, PAL_BUTTON1); 	sample_t *s = &instr[editor.curInstr]->smp[editor.curSmp]; 	double dLenMul = exp2(smpEd_RelReSmp * (1.0 / 12.0)); 	double dNewLen = s->length * dLenMul;	if (dNewLen > (double)MAX_SAMPLE_LEN)		dNewLen = (double)MAX_SAMPLE_LEN; 	textOutShadow(215, 236, PAL_FORGRND, PAL_BUTTON2, "Rel. h.tones");	textOutShadow(215, 250, PAL_FORGRND, PAL_BUTTON2, "New sample size");	hexOut(361, 250, PAL_FORGRND, (int32_t)dNewLen, 8); 	     if (smpEd_RelReSmp == 0) sign = ' ';	else if (smpEd_RelReSmp  < 0) sign = '-';	else sign = '+'; 	uint16_t val = ABS(smpEd_RelReSmp);	if (val > 9)	{		charOut(291, 236, PAL_FORGRND, sign);		charOut(298, 236, PAL_FORGRND, '0' + ((val / 10) % 10));		charOut(305, 236, PAL_FORGRND, '0' + (val % 10));	}	else	{		charOut(298, 236, PAL_FORGRND, sign);		charOut(305, 236, PAL_FORGRND, '0' + (val % 10));	}} static void setupResampleBoxWidgets(void){	pushButton_t *p;	scrollBar_t *s; 	// "Apply" pushbutton	p = &pushButtons[0];	memset(p, 0, sizeof (pushButton_t));	p->caption = "Apply";	p->x = 214;	p->y = 264;	p->w = 73;	p->h = 16;	p->callbackFuncOnUp = pbDoResampling;	p->visible = true; 	// "Exit" pushbutton	p = &pushButtons[1];	memset(p, 0, sizeof (pushButton_t));	p->caption = "Exit";	p->x = 345;	p->y = 264;	p->w = 73;	p->h = 16;	p->callbackFuncOnUp = pbExit;	p->visible = true; 	// scrollbar buttons 	p = &pushButtons[2];	memset(p, 0, sizeof (pushButton_t));	p->caption = ARROW_LEFT_STRING;	p->x = 314;	p->y = 234;	p->w = 23;	p->h = 13;	p->preDelay = 1;	p->delayFrames = 3;	p->callbackFuncOnDown = pbResampleTonesDown;	p->visible = true; 	p = &pushButtons[3];	memset(p, 0, sizeof (pushButton_t));	p->caption = ARROW_RIGHT_STRING;	p->x = 395;	p->y = 234;	p->w = 23;	p->h = 13;	p->preDelay = 1;	p->delayFrames = 3;	p->callbackFuncOnDown = pbResampleTonesUp;	p->visible = true; 	// echo num scrollbar	s = &scrollBars[0];	memset(s, 0, sizeof (scrollBar_t));	s->x = 337;	s->y = 234;	s->w = 58;	s->h = 13;	s->callbackFunc = sbSetResampleTones;	s->visible = true;	setScrollBarPageLength(0, 1);	setScrollBarEnd(0, 36 * 2);} void pbSampleResample(void){	uint16_t i; 	if (editor.curInstr == 0 ||		instr[editor.curInstr] == NULL ||		instr[editor.curInstr]->smp[editor.curSmp].dataPtr == NULL)	{		return;	} 	setupResampleBoxWidgets();	windowOpen(); 	outOfMemory = false; 	exitFlag = false;	while (ui.sysReqShown)	{		readInput();		if (ui.sysReqEnterPressed)			pbDoResampling(); 		setSyncedReplayerVars();		handleRedrawing(); 		drawResampleBox();		setScrollBarPos(0, smpEd_RelReSmp + 36, false);		drawCheckBox(0);		for (i = 0; i < 4; i++) drawPushButton(i);		drawScrollBar(0); 		flipFrame();	} 	for (i = 0; i < 4; i++) hidePushButton(i);	hideScrollBar(0); 	windowClose(false); 	if (outOfMemory)		okBox(0, "System message", "Not enough memory!");} static void cbEchoAddMemory(void){	echo_AddMemory ^= 1;} static void sbSetEchoNumPos(uint32_t pos){	if (echo_nEcho != (int32_t)pos)		echo_nEcho = (int16_t)pos;} static void sbSetEchoDistPos(uint32_t pos){	if (echo_Distance != (int32_t)pos)		echo_Distance = (int32_t)pos;} static void sbSetEchoFadeoutPos(uint32_t pos){	if (echo_VolChange != (int32_t)pos)		echo_VolChange = (int16_t)pos;} static void pbEchoNumDown(void){	if (echo_nEcho > 0)		echo_nEcho--;} static void pbEchoNumUp(void){	if (echo_nEcho < 64)		echo_nEcho++;} static void pbEchoDistDown(void){	if (echo_Distance > 0)		echo_Distance--;} static void pbEchoDistUp(void){	if (echo_Distance < 16384)		echo_Distance++;} static void pbEchoFadeoutDown(void){	if (echo_VolChange > 0)		echo_VolChange--;} static void pbEchoFadeoutUp(void){	if (echo_VolChange < 100)		echo_VolChange++;} static int32_t SDLCALL createEchoThread(void *ptr){	smpPtr_t sp; 	if (echo_nEcho < 1)	{		ui.sysReqShown = false;		return true;	} 	sample_t *s = &instr[editor.curInstr]->smp[editor.curSmp]; 	int32_t readLen = s->length;	int8_t *readPtr = s->dataPtr;	bool sample16Bit = !!(s->flags & SAMPLE_16BIT);	int32_t distance = echo_Distance * 16;	double dVolChange = echo_VolChange / 100.0; 	// calculate real number of echoes	double dSmp = sample16Bit ? 32768.0 : 128.0;	int32_t k = 0;	while (k++ < echo_nEcho && dSmp >= 1.0)		dSmp *= dVolChange;	int32_t nEchoes = k + 1; 	if (nEchoes < 1)	{		ui.sysReqShown = false;		return true;	} 	// set write length (either original length or full echo length)	int32_t writeLen = readLen;	if (echo_AddMemory)	{		int64_t tmp64 = (int64_t)distance * (nEchoes - 1); 		tmp64 += writeLen;		if (tmp64 > MAX_SAMPLE_LEN)			tmp64 = MAX_SAMPLE_LEN; 		writeLen = (uint32_t)tmp64;	} 	if (!allocateSmpDataPtr(&sp, writeLen, sample16Bit))	{		outOfMemory = true;		setMouseBusy(false);		ui.sysReqShown = false;		return false;	} 	pauseAudio();	unfixSample(s); 	int32_t writeIdx = 0; 	if (sample16Bit)	{		const int16_t *readPtr16 = (const int16_t *)readPtr;		int16_t *writePtr16 = (int16_t *)sp.ptr; 		while (writeIdx < writeLen)		{			double dSmpOut = 0.0;			double dSmpMul = 1.0; 			int32_t echoRead = writeIdx;			int32_t echoCycle = nEchoes; 			while (!stopThread)			{				if (echoRead < readLen)					dSmpOut += (int32_t)readPtr16[echoRead] * dSmpMul; 				dSmpMul *= dVolChange; 				echoRead -= distance;				if (echoRead <= 0 || --echoCycle <= 0)					break;			} 			DROUND(dSmpOut); 			int32_t smp32 = (int32_t)dSmpOut;			CLAMP16(smp32);			writePtr16[writeIdx++] = (int16_t)smp32;		}	}	else // 8-bit	{

Lines 1–500 of 1664.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t