// 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. Load more
// 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; // globals int32_t smpEd_Rx1 = 0, smpEd_Rx2 = 0; // allocs sample with proper alignment and padding for branchless resampling interpolation bool 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 interpolation bool 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 interpolation bool 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/end void 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]; } }