Olav SørensenPushed v1.66 codef56d9f63 years agoHistory
3868 lines · 83.4 KB · C
RawDownload
// 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>#ifndef _WIN32#include <unistd.h> // chdir() in UNICHAR_CHDIR()#endif#if defined _WIN32 || defined __amd64__ || (defined __i386__ && defined __SSE2__)#include <emmintrin.h>#endif#include "ft2_header.h"#include "ft2_config.h"#include "ft2_audio.h"#include "ft2_pattern_ed.h"#include "ft2_gui.h"#include "scopes/ft2_scopes.h"#include "ft2_video.h"#include "ft2_inst_ed.h"#include "ft2_sample_ed.h"#include "ft2_sample_saver.h"#include "ft2_mouse.h"#include "ft2_diskop.h"#include "ft2_keyboard.h"#include "ft2_structs.h"#include "ft2_replayer.h"#include "mixer/ft2_windowed_sinc.h" // SINC_TAPS, SINC_NEGATIVE_TAPS static const char sharpNote1Char[12] = { 'C', 'C', 'D', 'D', 'E', 'F', 'F', 'G', 'G', 'A', 'A', 'B' };static const char sharpNote2Char[12] = { '-', '#', '-', '#', '-', '-', '#', '-', '#', '-', '#', '-' };static const char flatNote1Char[12]  = { 'C', 'D', 'D', 'E', 'E', 'F', 'G', 'G', 'A', 'A', 'B', 'B' };static const char flatNote2Char[12]  = { '-', 'b', '-', 'b', '-', '-', 'b', '-', 'b', '-', 'b', '-' }; static char smpEd_SysReqText[64];static int8_t *smpCopyBuff;static bool updateLoopsOnMouseUp, writeSampleFlag, smpCopyDidCopyWholeSample;static int32_t smpEd_OldSmpPosLine = -1;static int32_t smpEd_ViewSize, smpEd_ScrPos, smpCopySize, smpCopyBits;static int32_t old_Rx1, old_Rx2, old_ViewSize, old_SmpScrPos;static int32_t lastMouseX, lastMouseY, lastDrawX, lastDrawY, mouseXOffs, curSmpLoopStart, curSmpLoopLength;static double dScrPosScaled, dPos2ScrMul, dScr2SmpPosMul;static sample_t smpCopySample;static SDL_Thread *thread; // globalsint32_t smpEd_Rx1 = 0, smpEd_Rx2 = 0; // allocs sample with proper alignment and padding for branchless resampling interpolationbool allocateSmpData(sample_t *s, int32_t length, bool sample16Bit){	if (sample16Bit)		length <<= 1; 	s->origDataPtr = (int8_t *)malloc(length + SAMPLE_PAD_LENGTH);	if (s->origDataPtr == NULL)	{		s->dataPtr = NULL;		return false;	} 	s->dataPtr = s->origDataPtr + SMP_DAT_OFFSET;	return true;} bool allocateSmpDataPtr(smpPtr_t *sp, int32_t length, bool sample16Bit){	if (sample16Bit)		length <<= 1; 	int8_t *newPtr = (int8_t *)malloc(length + SAMPLE_PAD_LENGTH);	if (newPtr == NULL)		return false; 	sp->origPtr = newPtr; 	sp->ptr = sp->origPtr + SMP_DAT_OFFSET;	return true;} // reallocs sample with proper alignment and padding for branchless resampling interpolationbool reallocateSmpData(sample_t *s, int32_t length, bool sample16Bit){	if (s->origDataPtr == NULL)		return allocateSmpData(s, length, sample16Bit); 	if (sample16Bit)		length <<= 1; 	int8_t *newPtr = (int8_t *)realloc(s->origDataPtr, length + SAMPLE_PAD_LENGTH);	if (newPtr == NULL)		return false; 	s->origDataPtr = newPtr;	s->dataPtr = s->origDataPtr + SMP_DAT_OFFSET; 	return true;} // reallocs sample with proper alignment and padding for branchless resampling interpolationbool reallocateSmpDataPtr(smpPtr_t *sp, int32_t length, bool sample16Bit){	if (sp->origPtr == NULL)		return allocateSmpDataPtr(sp, length, sample16Bit); 	if (sample16Bit)		length <<= 1; 	int8_t *newPtr = (int8_t *)realloc(sp->origPtr, length + SAMPLE_PAD_LENGTH);	if (newPtr == NULL)		return false; 	sp->origPtr = newPtr;	sp->ptr = sp->origPtr + SMP_DAT_OFFSET; 	return true;} void setSmpDataPtr(sample_t *s, smpPtr_t *sp){	s->origDataPtr = sp->origPtr;	s->dataPtr = sp->ptr;} void freeSmpDataPtr(smpPtr_t *sp){	if (sp->origPtr != NULL)	{		free(sp->origPtr);		sp->origPtr = NULL;	} 	sp->ptr = NULL;} void freeSmpData(sample_t *s){	if (s->origDataPtr != NULL)	{		free(s->origDataPtr);		s->origDataPtr = NULL;	} 	s->dataPtr = NULL;	s->isFixed = false;} bool cloneSample(sample_t *src, sample_t *dst){	smpPtr_t sp; 	freeSmpData(dst); 	if (src == NULL)	{		memset(dst, 0, sizeof (sample_t));	}	else	{		memcpy(dst, src, sizeof (sample_t)); 		// zero out stuff that wasn't supposed to be cloned		dst->origDataPtr = dst->dataPtr = NULL;		dst->isFixed = false;		dst->fixedPos = 0; 		// if source sample isn't empty, allocate room and copy it over (and fix it)		if (src->length > 0 && src->dataPtr != NULL)		{			bool sample16Bit = !!(src->flags & SAMPLE_16BIT);			if (!allocateSmpDataPtr(&sp, src->length, sample16Bit))			{				dst->length = 0;				return false;			} 			setSmpDataPtr(dst, &sp);			memcpy(dst->dataPtr, src->dataPtr, src->length << sample16Bit);			fixSample(dst);		}	} 	return true;} sample_t *getCurSample(void){	if (editor.curInstr == 0 || instr[editor.curInstr] == NULL)		return NULL; 	return &instr[editor.curInstr]->smp[editor.curSmp];} void sanitizeSample(sample_t *s){	if (s == NULL)		return; 	// if a sample has both forward loop and pingpong loop set, it means pingpong loop (FT2 mixer behavior)	if (GET_LOOPTYPE(s->flags) == (LOOP_FWD | LOOP_BIDI))		s->flags &= ~LOOP_FWD; // remove forward loop flag 	if (s->volume > 64)		s->volume = 64; 	s->relativeNote = CLAMP(s->relativeNote, -48, 71);	s->length = CLAMP(s->length, 0, MAX_SAMPLE_LEN); 	if (s->loopStart < 0 || s->loopLength <= 0 || s->loopStart+s->loopLength > s->length)	{		s->loopStart = 0;		s->loopLength = 0;		DISABLE_LOOP(s->flags);	}} static int32_t myMod(int32_t a, int32_t b) // works on negative numbers!{	int32_t c = a % b;	return (c < 0) ? (c + b) : c;} // modifies samples before index 0, and after loop/end (for branchless mixer interpolation (kinda))void fixSample(sample_t *s){	int32_t pos;	bool backwards; 	assert(s != NULL);	if (s->dataPtr == NULL || s->length <= 0)	{		s->isFixed = false;		s->fixedPos = 0;		return; // empty sample	} 	const bool sample16Bit = !!(s->flags & SAMPLE_16BIT);	int16_t *ptr16 = (int16_t *)s->dataPtr;	uint8_t loopType = GET_LOOPTYPE(s->flags);	int32_t length = s->length;	int32_t loopStart = s->loopStart;	int32_t loopLength = s->loopLength;	int32_t loopEnd = s->loopStart + s->loopLength; 	// treat loop as disabled if loopLen == 0 (FT2 does this)	if (loopType != 0 && loopLength <= 0)	{		loopType = 0;		loopStart = loopLength = loopEnd = 0;	} 	/* All negative taps should be equal to the first sample point when at sampling	** position #0 (on sample trigger), until an eventual loop cycle, where we do	** a special left edge case with replaced tap data.	** The sample pointer is offset and has allocated data before it, so this is	** safe.	*/	if (sample16Bit)	{		for (int32_t i = 0; i < SINC_MAX_LEFT_TAPS; i++)			ptr16[i-SINC_MAX_LEFT_TAPS] = ptr16[0];	}	else	{		for (int32_t i = 0; i < SINC_MAX_LEFT_TAPS; i++)			s->dataPtr[i-SINC_MAX_LEFT_TAPS] = s->dataPtr[0];	} 	if (loopType == LOOP_OFF) // no loop	{		if (sample16Bit)		{			for (int32_t i = 0; i < SINC_MAX_RIGHT_TAPS; i++)				ptr16[length+i] = ptr16[length-1];		}		else		{			for (int32_t i = 0; i < SINC_MAX_RIGHT_TAPS; i++)				s->dataPtr[length+i] = s->dataPtr[length-1];		} 		s->fixedPos = 0; // this value is not used for non-looping samples, set to zero		s->isFixed = false; // no fixed samples inside actual sample data		return;	} 	s->fixedPos = loopEnd;	s->isFixed = true; 	if (loopType == LOOP_FWD) // forward loop	{		if (sample16Bit)		{			// left edge (we need SINC_MAX_TAPS amount of taps starting from the center tap)			for (int32_t i = -SINC_MAX_LEFT_TAPS; i < SINC_MAX_TAPS; i++)			{				pos = loopStart + myMod(i, loopLength);				s->leftEdgeTapSamples16[SINC_MAX_LEFT_TAPS+i] = ptr16[pos];			} 			// right edge (change actual sample data since data after loop is never used)			pos = loopStart;			for (int32_t i = 0; i < SINC_MAX_RIGHT_TAPS; i++)			{				s->fixedSmp[i] = ptr16[loopEnd+i];				ptr16[loopEnd+i] = ptr16[pos]; 				if (++pos >= loopEnd)					pos -= loopLength;			}		}		else // 8-bit		{			// left edge (we need SINC_MAX_TAPS amount of taps starting from the center tap)			for (int32_t i = -SINC_MAX_LEFT_TAPS; i < SINC_MAX_TAPS; i++)			{				pos = loopStart + myMod(i, loopLength);				s->leftEdgeTapSamples8[SINC_MAX_LEFT_TAPS+i] = s->dataPtr[pos];			} 			// right edge (change actual sample data since data after loop is never used)			pos = loopStart;			for (int32_t i = 0; i < SINC_MAX_RIGHT_TAPS; i++)			{				s->fixedSmp[i] = s->dataPtr[loopEnd+i];				s->dataPtr[loopEnd+i] = s->dataPtr[pos]; 				if (++pos >= loopEnd)					pos -= loopLength;			}		}	}	else // pingpong loop	{		if (sample16Bit)		{			// left edge (positive taps, we need SINC_MAX_TAPS amount of taps starting from the center tap)			pos = loopStart;			backwards = false;			for (int32_t i = 0; i < SINC_MAX_TAPS; i++)			{				if (backwards)				{					if (pos < loopStart)					{						pos = loopStart;						backwards = false;					}				}				else if (pos >= loopEnd) // forwards				{					pos = loopEnd-1;					backwards = true;				} 				s->leftEdgeTapSamples16[SINC_MAX_LEFT_TAPS+i] = ptr16[pos]; 				if (backwards)					pos--;				else					pos++;			} 			// left edge (negative taps)			for (int32_t i = 0; i < SINC_MAX_LEFT_TAPS; i++)				s->leftEdgeTapSamples16[(SINC_MAX_LEFT_TAPS-1)-i] = s->leftEdgeTapSamples16[SINC_MAX_LEFT_TAPS+1+i]; 			// right edge (change actual sample data since data after loop is never used)			pos = loopEnd-1;			backwards = true;			for (int32_t i = 0; i < SINC_MAX_RIGHT_TAPS; i++)			{				if (backwards)				{					if (pos < loopStart)					{						pos = loopStart;						backwards = false;					}				}				else if (pos >= loopEnd) // forwards				{					pos = loopEnd-1;					backwards = true;				} 				s->fixedSmp[i] = ptr16[loopEnd+i];				ptr16[loopEnd+i] = ptr16[pos]; 				if (backwards)					pos--;				else					pos++;			}		}		else // 8-bit		{			// left edge (positive taps, we need SINC_MAX_TAPS amount of taps starting from the center tap)			pos = loopStart;			backwards = false;			for (int32_t i = 0; i < SINC_MAX_TAPS; i++)			{				if (backwards)				{					if (pos < loopStart)					{						pos = loopStart;						backwards = false;					}				}				else if (pos >= loopEnd) // forwards				{					pos = loopEnd-1;					backwards = true;				} 				s->leftEdgeTapSamples8[SINC_MAX_LEFT_TAPS+i] = s->dataPtr[pos]; 				if (backwards)					pos--;				else					pos++;			} 			// left edge (negative taps)			for (int32_t i = 0; i < SINC_MAX_LEFT_TAPS; i++)				s->leftEdgeTapSamples8[(SINC_MAX_LEFT_TAPS-1)-i] = s->leftEdgeTapSamples8[SINC_MAX_LEFT_TAPS+1+i]; 			// right edge (change actual sample data since data after loop is never used)			pos = loopEnd-1;			backwards = true;			for (int32_t i = 0; i < SINC_MAX_RIGHT_TAPS; i++)			{				if (backwards)				{					if (pos < loopStart)					{						pos = loopStart;						backwards = false;					}				}				else if (pos >= loopEnd) // forwards				{					pos = loopEnd-1;					backwards = true;				} 				s->fixedSmp[i] = s->dataPtr[loopEnd+i];				s->dataPtr[loopEnd+i] = s->dataPtr[pos]; 				if (backwards)					pos--;				else					pos++;			}		}	}} // restores interpolation tap samples after loop/endvoid unfixSample(sample_t *s){	assert(s != NULL);	if (s->dataPtr == NULL || !s->isFixed)		return; // empty sample or not fixed (f.ex. no loop) 	if (s->flags & SAMPLE_16BIT)	{		int16_t *ptr16 = (int16_t *)s->dataPtr + s->fixedPos;		for (int32_t i = 0; i < SINC_MAX_RIGHT_TAPS; i++)			ptr16[i] = s->fixedSmp[i];	}	else // 8-bit	{		int8_t *ptr8 = s->dataPtr + s->fixedPos;		for (int32_t i = 0; i < SINC_MAX_RIGHT_TAPS; i++)			ptr8[i] = (int8_t)s->fixedSmp[i];	} 	s->isFixed = false;} double getSampleValue(int8_t *smpData, int32_t position, bool sample16Bit){	if (smpData == NULL)		return 0; 	if (sample16Bit)	{		position <<= 1;		return *((int16_t *)&smpData[position]);	}	else	{		return smpData[position];	}}

Lines 1–500 of 3868.

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