1212 lines · 24.5 KB · C
RawDownload
// for finding memory leaks in debug mode with Visual Studio#if defined _DEBUG && defined _MSC_VER#include <crtdbg.h>#endif #include <stdint.h>#include <stdbool.h>#include <stdio.h>#include <math.h>#include "ft2_header.h"#include "ft2_sample_ed.h"#include "ft2_gui.h"#include "scopes/ft2_scopes.h"#include "ft2_pattern_ed.h"#include "ft2_replayer.h"#include "ft2_audio.h"#include "ft2_mouse.h"#include "ft2_structs.h" // this is truly a mess, but it works... static char byteFormatBuffer[64], tmpInstrName[1 + MAX_INST][22 + 1], tmpInstName[MAX_INST][22 + 1];static bool removePatt, removeInst, removeSamp, removeChans, removeSmpDataAfterLoop, convSmpsTo8Bit;static uint8_t instrUsed[MAX_INST], instrOrder[MAX_INST], pattUsed[MAX_PATTERNS], pattOrder[MAX_PATTERNS];static int16_t oldPattLens[MAX_PATTERNS], tmpPattLens[MAX_PATTERNS];static int64_t xmSize64 = -1, xmAfterTrimSize64 = -1, spaceSaved64 = -1;static note_t *oldPatts[MAX_PATTERNS], *tmpPatt[MAX_PATTERNS];static instr_t *tmpInstr[1 + MAX_INST], *tmpInst[MAX_INST]; // tmpInstr[x] = copy of instr[x] for "after trim" size calculationstatic SDL_Thread *trimThread; void pbTrimCalc(void); static void freeTmpInstruments(void){	for (int32_t i = 0; i <= MAX_INST; i++)	{		if (tmpInstr[i] != NULL)		{			// don't free samples, as the pointers are shared with main instruments... 			free(tmpInstr[i]);			tmpInstr[i] = NULL;		}	}} static bool setTmpInstruments(void){	freeTmpInstruments(); 	for (int32_t i = 0; i <= MAX_INST; i++)	{		if (instr[i] != NULL)		{			tmpInstr[i] = (instr_t *)malloc(sizeof (instr_t));			if (tmpInstr[i] == NULL)			{				freeTmpInstruments();				return false;			} 			*tmpInstr[i] = *instr[i];		}	} 	return true;} static void remapInstrInSong(uint8_t src, uint8_t dst, int32_t ap){	for (int32_t i = 0; i < ap; i++)	{		note_t *pattPtr = pattern[i];		if (pattPtr == NULL)			continue; 		const int32_t readLen = patternNumRows[i] * MAX_CHANNELS; 		note_t *p = pattPtr;		for (int32_t j = 0; j < readLen; j++, p++)		{			if (p->instr == src)				p->instr = dst;		}	}} static int16_t getUsedTempSamples(uint16_t insNum){	if (tmpInstr[insNum] == NULL)		return 0; 	instr_t *ins = tmpInstr[insNum]; 	int16_t i = 16 - 1;	while (i >= 0 && ins->smp[i].dataPtr == NULL && ins->smp[i].name[0] == '\0')		i--; 	/* Yes, 'i' can be -1 here, and will be set to at least 0	** because of ins->ta values. Possibly an FT2 bug...	**/	for (int16_t j = 0; j < 96; j++)	{		if (ins->note2SampleLUT[j] > i)			i = ins->note2SampleLUT[j];	} 	return i+1;} static int64_t getTempInsAndSmpSize(void){	int16_t j; 	int16_t ai = MAX_INST;	while (ai > 0 && getUsedTempSamples(ai) == 0 && tmpInstrName[ai][0] == '\0')		ai--; 	int64_t currSize64 = 0; 	// count instrument and sample data size in song	for (int16_t i = 1; i <= ai; i++)	{		if (tmpInstr[i] == NULL)			j = 0;		else			j = i; 		const int16_t a = getUsedTempSamples(i);		if (a > 0)			currSize64 += INSTR_HEADER_SIZE + (a * sizeof (xmSmpHdr_t));		else			currSize64 += 22+11; 		instr_t *ins = tmpInstr[j];		for (int16_t k = 0; k < a; k++)		{			sample_t *s = &ins->smp[k];			if (s->dataPtr != NULL && s->length > 0)			{				if (s->flags & SAMPLE_16BIT)					currSize64 += s->length << 1;				else					currSize64 += s->length;			}		}	} 	return currSize64;} static void wipeInstrUnused(bool testWipeSize, int16_t *ai, int32_t ap, int32_t antChn){	int16_t numRows;	int32_t i, j, k;	note_t *p; 	int32_t numInsts = *ai; 	// calculate what instruments are used	memset(instrUsed, 0, numInsts);	for (i = 0; i < ap; i++)	{		if (testWipeSize)		{			p = tmpPatt[i];			numRows = tmpPattLens[i];		}		else		{			p = pattern[i];			numRows = patternNumRows[i];		} 		if (p == NULL)			continue; 		for (j = 0; j < numRows; j++)		{			for (k = 0; k < antChn; k++)			{				uint8_t ins = p[(j * MAX_CHANNELS) + k].instr;				if (ins > 0 && ins <= MAX_INST)					instrUsed[ins-1] = true;			}		}	} 	int16_t instToDel = 0;	uint8_t newInst = 0;	int16_t newNumInsts = 0; 	memset(instrOrder, 0, numInsts);	for (i = 0; i < numInsts; i++)	{		if (instrUsed[i])		{			newNumInsts++;			instrOrder[i] = newInst++;		}		else		{			instToDel++;		}	} 	if (instToDel == 0)		return; 	if (testWipeSize)	{		for (i = 0; i < numInsts; i++)		{			if (!instrUsed[i] && tmpInstr[1+i] != NULL)			{				free(tmpInstr[1+i]);				tmpInstr[1+i] = NULL;			}		} 		// relocate instruments 		memcpy(tmpInstName, &tmpInstrName[1], MAX_INST * sizeof (song.instrName[0]));		memcpy(tmpInst, &tmpInstr[1], MAX_INST * sizeof (instr[0])); 		memset(&tmpInstr[1], 0, numInsts * sizeof (tmpInstr[0]));		memset(&tmpInstrName[1], 0, numInsts * sizeof (tmpInstrName[0])); 		for (i = 0; i < numInsts; i++)		{			if (instrUsed[i])			{				newInst = instrOrder[i]; 				memcpy(&tmpInstr[1+newInst], &tmpInst[i], sizeof (tmpInst[0]));				strcpy(tmpInstrName[1+newInst], tmpInstName[i]);			}		} 		*ai = newNumInsts;		return;	} 	// clear unused instruments	for (i = 0; i < numInsts; i++)	{		if (!instrUsed[i])			freeInstr(1 + i);	} 	// relocate instruments 	memcpy(tmpInstName, &song.instrName[1], MAX_INST * sizeof (song.instrName[0]));	memcpy(tmpInst, &instr[1], MAX_INST * sizeof (instr[0])); 	memset(&instr[1], 0, numInsts * sizeof (instr[0]));	memset(song.instrName[1], 0, numInsts * sizeof (song.instrName[0])); // XXX: Is this safe? 	for (i = 0; i < numInsts; i++)	{		if (instrUsed[i])		{			newInst = instrOrder[i];			remapInstrInSong(1 + (uint8_t)i, 1 + newInst, ap); 			memcpy(&instr[1+newInst], &tmpInst[i], sizeof (instr[0]));			strcpy(song.instrName[1+newInst], tmpInstName[i]);		}	} 	*ai = newNumInsts; 	setTmpInstruments();} static void wipePattsUnused(bool testWipeSize, int16_t *ap){	uint8_t newPatt;	int16_t i, *pLens;	note_t **p; 	int16_t usedPatts = *ap;	memset(pattUsed, 0, usedPatts); 	int16_t newUsedPatts = 0;	for (i = 0; i < song.songLength; i++)	{		newPatt = song.orders[i];		if (newPatt < usedPatts && !pattUsed[newPatt])		{			pattUsed[newPatt] = true;			newUsedPatts++;		}	} 	if (newUsedPatts == 0 || newUsedPatts == usedPatts)		return; // nothing to do! 	newPatt = 0;	memset(pattOrder, 0, usedPatts);	for (i = 0; i < usedPatts; i++)	{		if (pattUsed[i])			pattOrder[i] = newPatt++;	} 	if (testWipeSize)	{		p = tmpPatt;		pLens = tmpPattLens;	}	else	{		p = pattern;		pLens = patternNumRows;	} 	memcpy(oldPatts, p, usedPatts * sizeof (note_t *));	memcpy(oldPattLens, pLens, usedPatts * sizeof (int16_t));	memset(p, 0, usedPatts * sizeof (note_t *));	memset(pLens, 0, usedPatts * sizeof (int16_t)); 	// relocate patterns	for (i = 0; i < usedPatts; i++)	{		p[i] = NULL; 		if (!pattUsed[i])		{			if (!testWipeSize && oldPatts[i] != NULL)			{				free(oldPatts[i]);				oldPatts[i] = NULL;			}		}		else		{			newPatt = pattOrder[i];			p[newPatt] = oldPatts[i];			pLens[newPatt] = oldPattLens[i];		}	} 	if (!testWipeSize)	{		for (i = 0; i < MAX_PATTERNS; i++)		{			if (pattern[i] == NULL)				patternNumRows[i] = 64;		} 		// reorder order list (and clear unused entries)		for (i = 0; i < 256; i++)		{			if (i < song.songLength)				song.orders[i] = pattOrder[song.orders[i]];			else				song.orders[i] = 0;		}	} 	*ap = newUsedPatts;} static void wipeSamplesUnused(bool testWipeSize, int16_t ai){	uint8_t smpUsed[16], smpOrder[16];	int16_t j, k, l;	instr_t *ins;	sample_t tempSamples[16]; 	for (int16_t i = 1; i <= ai; i++)	{		if (!testWipeSize)		{			if (instr[i] == NULL)				l = 0;			else				l = i; 			ins = instr[l];			l = getUsedSamples(i);		}		else		{			if (tmpInstr[i] == NULL)				l = 0;			else				l = i; 			ins = tmpInstr[l];			l = getUsedTempSamples(i);		} 		memset(smpUsed, 0, l);		if (l > 0)		{			sample_t *s = ins->smp;			for (j = 0; j < l; j++, s++)			{				// check if sample is referenced in instrument				for (k = 0; k < 96; k++)				{					if (ins->note2SampleLUT[k] == j)					{						smpUsed[j] = true;						break; // sample is used					}				} 				if (k == 96)				{					// sample is unused 					if (s->dataPtr != NULL && !testWipeSize)						freeSmpData(s); 					memset(s, 0, sizeof (sample_t));				}			} 			// create re-order list			uint8_t newSamp = 0;			memset(smpOrder, 0, l);			for (j = 0; j < l; j++)			{				if (smpUsed[j])					smpOrder[j] = newSamp++;			} 			// re-order samples 			memcpy(tempSamples, ins->smp, l * sizeof (sample_t));			memset(ins->smp, 0, l * sizeof (sample_t)); 			for (j = 0; j < l; j++)			{				if (smpUsed[j])					ins->smp[smpOrder[j]] = tempSamples[j];			} 			// re-order note->sample list			for (j = 0; j < 96; j++)			{				newSamp = ins->note2SampleLUT[j];				if (smpUsed[newSamp])					ins->note2SampleLUT[j] = smpOrder[newSamp];				else					ins->note2SampleLUT[j] = 0;			}		}	}} static void wipeSmpDataAfterLoop(bool testWipeSize, int16_t ai){	int16_t l;	instr_t *ins; 	for (int16_t i = 1; i <= ai; i++)	{		if (!testWipeSize)		{			if (instr[i] == NULL)				l = 0;			else				l = i; 			ins = instr[l];			l = getUsedSamples(i);		}		else		{			if (tmpInstr[i] == NULL)				l = 0;			else				l = i; 			ins = tmpInstr[l];			l = getUsedTempSamples(i);		} 		sample_t *s = ins->smp;		for (int16_t j = 0; j < l; j++, s++)		{			if (s->dataPtr != NULL && GET_LOOPTYPE(s->flags) != LOOP_OFF && s->length > 0 && s->length > s->loopStart+s->loopLength)			{				if (!testWipeSize)					unfixSample(s); 				s->length = s->loopStart + s->loopLength;				if (!testWipeSize)				{					if (s->length <= 0)					{						s->length = 0;						freeSmpData(s);					}					else					{

Lines 1–500 of 1212.

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