ft2-clone

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

commit 163e75b7a70017da234a957f3e82d3dca51287e1
parent bcb94c43e4acd6ea5cbf1eda090386c2c86935f6
Author: Olav Sørensen <olav.sorensen@live.no>
Date:   Sat, 16 Dec 2023 19:47:10 +0100

Cubic spline interpolator added

Diffstat:
Msrc/ft2_audio.c | 34+++++++++++++++-------------------
Msrc/ft2_audio.h | 2+-
Msrc/ft2_config.c | 22++++++++++++++++------
Msrc/ft2_config.h | 2++
Msrc/ft2_header.h | 4++--
Msrc/ft2_main.c | 2+-
Msrc/ft2_radiobuttons.c | 9+++++----
Msrc/ft2_radiobuttons.h | 1+
Msrc/ft2_replayer.c | 2++
Msrc/ft2_replayer.h | 1+
Msrc/ft2_sample_ed.c | 70+++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/ft2_sample_saver.c | 6+++---
Msrc/helpdata/FT2.HLP | 8+++-----
Msrc/helpdata/ft2_help_data.h | 959+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/mixer/ft2_center_mix.c | 857+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/mixer/ft2_center_mix.h | 12++++++++++++
Asrc/mixer/ft2_cubic_spline.c | 41+++++++++++++++++++++++++++++++++++++++++
Asrc/mixer/ft2_cubic_spline.h | 21+++++++++++++++++++++
Msrc/mixer/ft2_mix.c | 886+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/mixer/ft2_mix.h | 4++++
Msrc/mixer/ft2_mix_macros.h | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/mixer/ft2_windowed_sinc.h | 9++++-----
Mvs2019_project/ft2-clone/ft2-clone.vcxproj | 2++
Mvs2019_project/ft2-clone/ft2-clone.vcxproj.filters | 6++++++
24 files changed, 2412 insertions(+), 649 deletions(-)

diff --git a/src/ft2_audio.c b/src/ft2_audio.c @@ -310,13 +310,13 @@ static void voiceTrigger(int32_t ch, sample_t *s, int32_t position) { v->base16 = (const int16_t *)s->dataPtr; v->revBase16 = &v->base16[loopStart + loopEnd]; // for pingpong loops - v->leftEdgeTaps16 = s->leftEdgeTapSamples16 + SINC_MAX_LEFT_TAPS; + v->leftEdgeTaps16 = s->leftEdgeTapSamples16 + MAX_LEFT_TAPS; } else { v->base8 = s->dataPtr; v->revBase8 = &v->base8[loopStart + loopEnd]; // for pingpong loops - v->leftEdgeTaps8 = s->leftEdgeTapSamples8 + SINC_MAX_LEFT_TAPS; + v->leftEdgeTaps8 = s->leftEdgeTapSamples8 + MAX_LEFT_TAPS; } v->hasLooped = false; // for sinc interpolation special case @@ -335,7 +335,7 @@ static void voiceTrigger(int32_t ch, sample_t *s, int32_t position) return; } - v->mixFuncOffset = ((int32_t)sample16Bit * 12) + (audio.interpolationType * 3) + loopType; + v->mixFuncOffset = ((int32_t)sample16Bit * 15) + (audio.interpolationType * 3) + loopType; v->active = true; } @@ -385,17 +385,13 @@ void updateVoices(void) { ch->oldFinalPeriod = ch->finalPeriod; - if (ch->finalPeriod == 0) // in FT2, period 0 -> delta 0 - { - v->oldDelta = 0; - v->fSincLUT = fKaiserSinc; - v->scopeDelta = 0; - } - else - { - const double dHz = dPeriod2Hz(ch->finalPeriod); - const uintCPUWord_t delta = v->oldDelta = (intCPUWord_t)((dHz * audio.dHz2MixDeltaMul) + 0.5); // Hz -> fixed-point delta (rounded) + const double dHz = dPeriod2Hz(ch->finalPeriod); + + // set voice delta + const uintCPUWord_t delta = v->oldDelta = (intCPUWord_t)((dHz * audio.dHz2MixDeltaMul) + 0.5); // Hz -> fixed-point delta (rounded) + if (audio.interpolationType == INTERPOLATION_SINC8 || audio.interpolationType == INTERPOLATION_SINC16) + { // decide which sinc LUT to use according to the resampling ratio if (delta <= (uintCPUWord_t)(1.1875 * MIXER_FRAC_SCALE)) v->fSincLUT = fKaiserSinc; @@ -403,11 +399,11 @@ void updateVoices(void) v->fSincLUT = fDownSample1; else v->fSincLUT = fDownSample2; - - // set scope delta - const double dHz2ScopeDeltaMul = SCOPE_FRAC_SCALE / (double)SCOPE_HZ; - v->scopeDelta = (intCPUWord_t)((dHz * dHz2ScopeDeltaMul) + 0.5); // Hz -> fixed-point delta (rounded) } + + // set scope delta + const double dHz2ScopeDeltaMul = SCOPE_FRAC_SCALE / (double)SCOPE_HZ; + v->scopeDelta = (intCPUWord_t)((dHz * dHz2ScopeDeltaMul) + 0.5); // Hz -> fixed-point delta (rounded) } v->delta = v->oldDelta; @@ -484,13 +480,13 @@ static void doChannelMixing(int32_t bufferPosition, int32_t samplesToMix) centerMixFlag = (v->fCurrVolumeL == v->fCurrVolumeR); } - mixFuncTab[((int32_t)centerMixFlag * (3*4*2*2)) + ((int32_t)volRampFlag * (3*4*2)) + v->mixFuncOffset](v, bufferPosition, samplesToMix); + mixFuncTab[((int32_t)centerMixFlag * (3*5*2*2)) + ((int32_t)volRampFlag * (3*5*2)) + v->mixFuncOffset](v, bufferPosition, samplesToMix); } if (r->active) // volume ramp fadeout-voice { const bool centerMixFlag = (r->fTargetVolumeL == r->fTargetVolumeR) && (r->fVolumeLDelta == r->fVolumeRDelta); - mixFuncTab[((int32_t)centerMixFlag * (3*4*2*2)) + (3*4*2) + r->mixFuncOffset](r, bufferPosition, samplesToMix); + mixFuncTab[((int32_t)centerMixFlag * (3*5*2*2)) + (3*5*2) + r->mixFuncOffset](r, bufferPosition, samplesToMix); } } } diff --git a/src/ft2_audio.h b/src/ft2_audio.h @@ -73,7 +73,7 @@ typedef struct uintCPUWord_t positionFrac, delta, oldDelta, scopeDelta; - // if (loopEnabled && hasLooped && samplingPos <= loopStart+SINC_MAX_LEFT_TAPS) readFixedTapsFromThisPointer(); + // if (loopEnabled && hasLooped && samplingPos <= loopStart+MAX_LEFT_TAPS) readFixedTapsFromThisPointer(); const int8_t *leftEdgeTaps8; const int16_t *leftEdgeTaps16; diff --git a/src/ft2_config.c b/src/ft2_config.c @@ -140,7 +140,8 @@ static void loadConfigFromBuffer(bool defaults) config.recMIDIVolSens = CLAMP(config.recMIDIVolSens, 0, 200); config.recMIDIChn = CLAMP(config.recMIDIChn, 1, 16); - config.interpolation &= 3; // one extra bit used in FT2 clone (off, sinc, linear) + if (config.interpolation > 4) + config.interpolation = INTERPOLATION_SINC8; // default (sinc, 8 point) if (config.recTrueInsert > 1) config.recTrueInsert = 1; @@ -834,6 +835,8 @@ void setConfigAudioRadioButtonStates(void) // accessed by other .c files tmpID = RB_CONFIG_AUDIO_INTRP_LINEAR; else if (config.interpolation == INTERPOLATION_SINC16) tmpID = RB_CONFIG_AUDIO_INTRP_SINC16; + else if (config.interpolation == INTERPOLATION_CUBIC) + tmpID = RB_CONFIG_AUDIO_INTRP_CUBIC; else tmpID = RB_CONFIG_AUDIO_INTRP_SINC8; // default case @@ -1168,11 +1171,11 @@ void showConfigScreen(void) textOutShadow(406, 75, PAL_FORGRND, PAL_DSKTOP2, "16-bit"); textOutShadow(406, 89, PAL_FORGRND, PAL_DSKTOP2, "32-bit (float)"); - textOutShadow(390, 105, PAL_FORGRND, PAL_DSKTOP2, "Interpolation:"); - textOutShadow(406, 118, PAL_FORGRND, PAL_DSKTOP2, "Disabled"); - textOutShadow(406, 132, PAL_FORGRND, PAL_DSKTOP2, "Linear (2 point)"); - textOutShadow(406, 146, PAL_FORGRND, PAL_DSKTOP2, "Sinc (8 point)"); - textOutShadow(406, 160, PAL_FORGRND, PAL_DSKTOP2, "Sinc (16 point)"); + textOutShadow(406, 105, PAL_FORGRND, PAL_DSKTOP2, "No interpolation"); + textOutShadow(406, 119, PAL_FORGRND, PAL_DSKTOP2, "Linear (FT2)"); + textOutShadow(406, 133, PAL_FORGRND, PAL_DSKTOP2, "Cubic spline"); + textOutShadow(406, 147, PAL_FORGRND, PAL_DSKTOP2, "Sinc (8 point)"); + textOutShadow(406, 161, PAL_FORGRND, PAL_DSKTOP2, "Sinc (16 point)"); textOutShadow(509, 3, PAL_FORGRND, PAL_DSKTOP2, "Audio output rate:"); textOutShadow(525, 17, PAL_FORGRND, PAL_DSKTOP2, "44100Hz"); @@ -1625,6 +1628,13 @@ void rbConfigAudioIntrpLinear(void) checkRadioButton(RB_CONFIG_AUDIO_INTRP_LINEAR); } +void rbConfigAudioIntrpCubic(void) +{ + config.interpolation = INTERPOLATION_CUBIC; + audioSetInterpolationType(config.interpolation); + checkRadioButton(RB_CONFIG_AUDIO_INTRP_CUBIC); +} + void rbConfigAudioIntrp8PointSinc(void) { config.interpolation = INTERPOLATION_SINC8; diff --git a/src/ft2_config.h b/src/ft2_config.h @@ -24,6 +24,7 @@ enum INTERPOLATION_SINC8 = 1, INTERPOLATION_LINEAR = 2, INTERPOLATION_SINC16 = 3, + INTERPOLATION_CUBIC = 4, // ------ MOUSE_IDLE_SHAPE_NICE = 0, @@ -219,6 +220,7 @@ void rbConfigAudio16Bit(void); void rbConfigAudio32BitFloat(void); void rbConfigAudioIntrpDisabled(void); void rbConfigAudioIntrpLinear(void); +void rbConfigAudioIntrpCubic(void); void rbConfigAudioIntrp8PointSinc(void); void rbConfigAudioIntrp16PointSinc(void); void rbConfigAudio44kHz(void); diff --git a/src/ft2_header.h b/src/ft2_header.h @@ -37,8 +37,8 @@ ** branchless in the inner channel mixer loop. ** Warning: Do not change this! */ -#define SMP_DAT_OFFSET ((SINC_MAX_LEFT_TAPS*2)+1) -#define SAMPLE_PAD_LENGTH (SMP_DAT_OFFSET+(SINC_MAX_RIGHT_TAPS*2)) +#define SMP_DAT_OFFSET ((MAX_LEFT_TAPS*2)+1) +#define SAMPLE_PAD_LENGTH (SMP_DAT_OFFSET+(MAX_RIGHT_TAPS*2)) #ifndef _WIN32 #define _stricmp strcasecmp diff --git a/src/ft2_main.c b/src/ft2_main.c @@ -155,7 +155,7 @@ int main(int argc, char *argv[]) return 1; } - if (!calcWindowedSincTables()) // must be called before config is loaded + if (!calcCubicSplineTable() || !calcWindowedSincTables()) // must be called before config is loaded { cleanUpAndExit(); return false; diff --git a/src/ft2_radiobuttons.c b/src/ft2_radiobuttons.c @@ -86,10 +86,11 @@ radioButton_t radioButtons[NUM_RADIOBUTTONS] = // audio interpolation //x, y, w, group, funcOnUp - { 390, 117, 65, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpDisabled }, - { 390, 131, 107, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpLinear }, - { 390, 145, 95, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrp8PointSinc }, - { 390, 159, 102, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrp16PointSinc }, + { 390, 104, 109, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpDisabled }, + { 390, 118, 91, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpLinear }, + { 390, 132, 86, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpCubic }, + { 390, 146, 95, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrp8PointSinc }, + { 390, 160, 102, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrp16PointSinc }, // audio output frequency //x, y, w, group, funcOnUp diff --git a/src/ft2_radiobuttons.h b/src/ft2_radiobuttons.h @@ -58,6 +58,7 @@ enum // RADIOBUTTONS // AUDIO INTERPOLATION RB_CONFIG_AUDIO_INTRP_DISABLED, RB_CONFIG_AUDIO_INTRP_LINEAR, + RB_CONFIG_AUDIO_INTRP_CUBIC, RB_CONFIG_AUDIO_INTRP_SINC8, RB_CONFIG_AUDIO_INTRP_SINC16, diff --git a/src/ft2_replayer.c b/src/ft2_replayer.c @@ -20,6 +20,7 @@ #include "ft2_sample_loader.h" #include "ft2_tables.h" #include "ft2_structs.h" +#include "mixer/ft2_cubic_spline.h" #include "mixer/ft2_windowed_sinc.h" static double dLogTab[4*12*16], dExp2MulTab[32]; @@ -2818,6 +2819,7 @@ void closeReplayer(void) instr[131] = NULL; } + freeCubicSplineTable(); freeWindowedSincTables(); } diff --git a/src/ft2_replayer.h b/src/ft2_replayer.h @@ -3,6 +3,7 @@ #include <stdint.h> #include <stdbool.h> #include "ft2_unicode.h" +#include "mixer/ft2_cubic_spline.h" #include "mixer/ft2_windowed_sinc.h" #include "ft2_cpu.h" diff --git a/src/ft2_sample_ed.c b/src/ft2_sample_ed.c @@ -260,25 +260,25 @@ void fixSample(sample_t *s) */ if (sample16Bit) { - for (int32_t i = 0; i < SINC_MAX_LEFT_TAPS; i++) - ptr16[i-SINC_MAX_LEFT_TAPS] = ptr16[0]; + for (int32_t i = 0; i < MAX_LEFT_TAPS; i++) + ptr16[i-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]; + for (int32_t i = 0; i < MAX_LEFT_TAPS; i++) + s->dataPtr[i-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++) + for (int32_t i = 0; i < MAX_RIGHT_TAPS; i++) ptr16[length+i] = ptr16[length-1]; } else { - for (int32_t i = 0; i < SINC_MAX_RIGHT_TAPS; i++) + for (int32_t i = 0; i < MAX_RIGHT_TAPS; i++) s->dataPtr[length+i] = s->dataPtr[length-1]; } @@ -294,16 +294,16 @@ void fixSample(sample_t *s) { 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++) + // left edge (we need MAX_TAPS amount of taps starting from the center tap) + for (int32_t i = -MAX_LEFT_TAPS; i < MAX_TAPS; i++) { pos = loopStart + myMod(i, loopLength); - s->leftEdgeTapSamples16[SINC_MAX_LEFT_TAPS+i] = ptr16[pos]; + s->leftEdgeTapSamples16[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++) + for (int32_t i = 0; i < MAX_RIGHT_TAPS; i++) { s->fixedSmp[i] = ptr16[loopEnd+i]; ptr16[loopEnd+i] = ptr16[pos]; @@ -314,16 +314,16 @@ void fixSample(sample_t *s) } 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++) + // left edge (we need MAX_TAPS amount of taps starting from the center tap) + for (int32_t i = -MAX_LEFT_TAPS; i < MAX_TAPS; i++) { pos = loopStart + myMod(i, loopLength); - s->leftEdgeTapSamples8[SINC_MAX_LEFT_TAPS+i] = s->dataPtr[pos]; + s->leftEdgeTapSamples8[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++) + for (int32_t i = 0; i < MAX_RIGHT_TAPS; i++) { s->fixedSmp[i] = s->dataPtr[loopEnd+i]; s->dataPtr[loopEnd+i] = s->dataPtr[pos]; @@ -337,10 +337,10 @@ void fixSample(sample_t *s) { if (sample16Bit) { - // left edge (positive taps, we need SINC_MAX_TAPS amount of taps starting from the center tap) + // left edge (positive taps, we need MAX_TAPS amount of taps starting from the center tap) pos = loopStart; backwards = false; - for (int32_t i = 0; i < SINC_MAX_TAPS; i++) + for (int32_t i = 0; i < MAX_TAPS; i++) { if (backwards) { @@ -356,7 +356,7 @@ void fixSample(sample_t *s) backwards = true; } - s->leftEdgeTapSamples16[SINC_MAX_LEFT_TAPS+i] = ptr16[pos]; + s->leftEdgeTapSamples16[MAX_LEFT_TAPS+i] = ptr16[pos]; if (backwards) pos--; @@ -365,13 +365,13 @@ void fixSample(sample_t *s) } // 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]; + for (int32_t i = 0; i < MAX_LEFT_TAPS; i++) + s->leftEdgeTapSamples16[(MAX_LEFT_TAPS-1)-i] = s->leftEdgeTapSamples16[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++) + for (int32_t i = 0; i < MAX_RIGHT_TAPS; i++) { if (backwards) { @@ -398,10 +398,10 @@ void fixSample(sample_t *s) } else // 8-bit { - // left edge (positive taps, we need SINC_MAX_TAPS amount of taps starting from the center tap) + // left edge (positive taps, we need MAX_TAPS amount of taps starting from the center tap) pos = loopStart; backwards = false; - for (int32_t i = 0; i < SINC_MAX_TAPS; i++) + for (int32_t i = 0; i < MAX_TAPS; i++) { if (backwards) { @@ -417,7 +417,7 @@ void fixSample(sample_t *s) backwards = true; } - s->leftEdgeTapSamples8[SINC_MAX_LEFT_TAPS+i] = s->dataPtr[pos]; + s->leftEdgeTapSamples8[MAX_LEFT_TAPS+i] = s->dataPtr[pos]; if (backwards) pos--; @@ -426,13 +426,13 @@ void fixSample(sample_t *s) } // 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]; + for (int32_t i = 0; i < MAX_LEFT_TAPS; i++) + s->leftEdgeTapSamples8[(MAX_LEFT_TAPS-1)-i] = s->leftEdgeTapSamples8[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++) + for (int32_t i = 0; i < MAX_RIGHT_TAPS; i++) { if (backwards) { @@ -470,13 +470,13 @@ void unfixSample(sample_t *s) 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++) + for (int32_t i = 0; i < 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++) + for (int32_t i = 0; i < MAX_RIGHT_TAPS; i++) ptr8[i] = (int8_t)s->fixedSmp[i]; } @@ -818,7 +818,7 @@ static int32_t getScaledSample(sample_t *s, int32_t index) // for sample data vi int16_t *ptr16 = (int16_t *)s->dataPtr; // don't read fixed mixer interpolation samples, read the prestine ones instead - if (index >= s->fixedPos && index < s->fixedPos+SINC_MAX_RIGHT_TAPS && s->length > loopEnd && s->isFixed) + if (index >= s->fixedPos && index < s->fixedPos+MAX_RIGHT_TAPS && s->length > loopEnd && s->isFixed) tmp32 = s->fixedSmp[index-s->fixedPos]; else tmp32 = ptr16[index]; @@ -827,7 +827,7 @@ static int32_t getScaledSample(sample_t *s, int32_t index) // for sample data vi } else // 8-bit { - if (index >= s->fixedPos && index < s->fixedPos+SINC_MAX_RIGHT_TAPS && s->length > loopEnd && s->isFixed) + if (index >= s->fixedPos && index < s->fixedPos+MAX_RIGHT_TAPS && s->length > loopEnd && s->isFixed) tmp32 = s->fixedSmp[index-s->fixedPos]; else tmp32 = s->dataPtr[index]; @@ -1095,7 +1095,7 @@ static void getMinMax8(const void *p, uint32_t scanLen, int8_t *min8, int8_t *ma } } -// for scanning sample data peak where loopEnd+SINC_MAX_RIGHT_TAPS is within scan range (fixed interpolation tap samples) +// for scanning sample data peak where loopEnd+MAX_RIGHT_TAPS is within scan range (fixed interpolation tap samples) static void getSpecialMinMax16(sample_t *s, int32_t index, int32_t scanEnd, int16_t *min16, int16_t *max16) { int16_t minVal2, maxVal2; @@ -1114,7 +1114,7 @@ static void getSpecialMinMax16(sample_t *s, int32_t index, int32_t scanEnd, int1 // read fixed samples (we are guaranteed to be within the fixed samples here) const int32_t tapIndex = index-s->fixedPos; - const int32_t scanLength = SINC_MAX_RIGHT_TAPS-tapIndex; + const int32_t scanLength = MAX_RIGHT_TAPS-tapIndex; int32_t tmpScanEnd = index+scanLength; if (tmpScanEnd > scanEnd) @@ -1140,7 +1140,7 @@ static void getSpecialMinMax16(sample_t *s, int32_t index, int32_t scanEnd, int1 *max16 = maxVal; } -// for scanning sample data peak where loopEnd+SINC_MAX_RIGHT_TAPS is within scan range (fixed interpolation tap samples) +// for scanning sample data peak where loopEnd+MAX_RIGHT_TAPS is within scan range (fixed interpolation tap samples) static void getSpecialMinMax8(sample_t *s, int32_t index, int32_t scanEnd, int8_t *min8, int8_t *max8) { int8_t minVal2, maxVal2; @@ -1159,7 +1159,7 @@ static void getSpecialMinMax8(sample_t *s, int32_t index, int32_t scanEnd, int8_ // read fixed samples (we are guaranteed to be within the fixed samples here) const int32_t tapIndex = index-s->fixedPos; - const int32_t scanLength = SINC_MAX_RIGHT_TAPS-tapIndex; + const int32_t scanLength = MAX_RIGHT_TAPS-tapIndex; int32_t tmpScanEnd = index+scanLength; if (tmpScanEnd > scanEnd) @@ -1204,7 +1204,7 @@ static void getSampleDataPeak(sample_t *s, int32_t index, int32_t length, int16_ /* If the scan area is including the fixed samples (for branchless mixer interpolation), ** do a special procedure to scan the original non-touched samples when needed. */ - const bool insideRange = index >= s->fixedPos && index < s->fixedPos+SINC_MAX_RIGHT_TAPS; + const bool insideRange = index >= s->fixedPos && index < s->fixedPos+MAX_RIGHT_TAPS; if (insideRange || (index < s->fixedPos && scanEnd >= s->fixedPos)) { if (s->flags & SAMPLE_16BIT) diff --git a/src/ft2_sample_saver.c b/src/ft2_sample_saver.c @@ -59,14 +59,14 @@ static void fileRestoreFixedSampleData(UNICHAR *filenameU, uint32_t sampleDataOf int32_t sampleFixPos = s->fixedPos; int32_t sampleFixOffset = 0; - int32_t samplesToWrite = SINC_MAX_RIGHT_TAPS; + int32_t samplesToWrite = MAX_RIGHT_TAPS; if (saveRangeFlag) { const int32_t markStart = getSampleRangeStart(); const int32_t markEnd = getSampleRangeEnd(); - if (markStart > sampleFixPos+SINC_MAX_RIGHT_TAPS || markEnd < sampleFixPos) + if (markStart > sampleFixPos+MAX_RIGHT_TAPS || markEnd < sampleFixPos) return; // nothing to do here if (markStart > sampleFixPos) @@ -80,7 +80,7 @@ static void fileRestoreFixedSampleData(UNICHAR *filenameU, uint32_t sampleDataOf if (sampleFixPos + samplesToWrite > markEnd) samplesToWrite = markEnd - sampleFixPos; - if (samplesToWrite < 0 || samplesToWrite > SINC_MAX_RIGHT_TAPS || sampleFixPos < 0 || sampleFixOffset < 0 || sampleFixOffset >= SINC_MAX_RIGHT_TAPS) + if (samplesToWrite < 0 || samplesToWrite > MAX_RIGHT_TAPS || sampleFixPos < 0 || sampleFixOffset < 0 || sampleFixOffset >= MAX_RIGHT_TAPS) return; } diff --git a/src/helpdata/FT2.HLP b/src/helpdata/FT2.HLP @@ -803,11 +803,9 @@ you exit the program. >@X040@C001Interpolation: >@X060@C002 Selects what type of resampling interpolation to use. -"Disabled" uses no interpolation (nearest neighbor), which will result in -aliasing (noise) in the sound. "Linear" is what real FT2 uses, -which is a mediocre interpolation type. "Sinc" is the recommended -setting for the best audio quality, although it may sometimes sound too filtered -and timbre-changing on low-quality samples. +If you want to have an authentic FT2 sound, select "linear". +Sinc will give the best interpolation, but it may sound too filtered on lo-fi samples. +Tip: Play around with the different options... >@X040@C001Volume ramping: >@X060@C002 diff --git a/src/helpdata/ft2_help_data.h b/src/helpdata/ft2_help_data.h @@ -3,9 +3,9 @@ #include <stdint.h> -#define HELP_DATA_LEN 27888 +#define HELP_DATA_LEN 27755 -const uint8_t helpData[27888] = +const uint8_t helpData[27755] = { 0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, @@ -1843,494 +1843,483 @@ const uint8_t helpData[27888] = 0x70,0x65,0x20,0x6F,0x66,0x20,0x72,0x65,0x73,0x61,0x6D,0x70, 0x6C,0x69,0x6E,0x67,0x20,0x69,0x6E,0x74,0x65,0x72,0x70,0x6F, 0x6C,0x61,0x74,0x69,0x6F,0x6E,0x20,0x74,0x6F,0x20,0x75,0x73, - 0x65,0x2E,0x49,0x22,0x44,0x69,0x73,0x61,0x62,0x6C,0x65,0x64, - 0x22,0x20,0x75,0x73,0x65,0x73,0x20,0x6E,0x6F,0x20,0x69,0x6E, - 0x74,0x65,0x72,0x70,0x6F,0x6C,0x61,0x74,0x69,0x6F,0x6E,0x20, - 0x28,0x6E,0x65,0x61,0x72,0x65,0x73,0x74,0x20,0x6E,0x65,0x69, - 0x67,0x68,0x62,0x6F,0x72,0x29,0x2C,0x20,0x77,0x68,0x69,0x63, - 0x68,0x20,0x77,0x69,0x6C,0x6C,0x20,0x72,0x65,0x73,0x75,0x6C, - 0x74,0x20,0x69,0x6E,0x3E,0x61,0x6C,0x69,0x61,0x73,0x69,0x6E, - 0x67,0x20,0x28,0x6E,0x6F,0x69,0x73,0x65,0x29,0x20,0x69,0x6E, - 0x20,0x74,0x68,0x65,0x20,0x73,0x6F,0x75,0x6E,0x64,0x2E,0x20, - 0x22,0x4C,0x69,0x6E,0x65,0x61,0x72,0x22,0x20,0x69,0x73,0x20, - 0x77,0x68,0x61,0x74,0x20,0x72,0x65,0x61,0x6C,0x20,0x46,0x54, - 0x32,0x20,0x75,0x73,0x65,0x73,0x2C,0x41,0x77,0x68,0x69,0x63, - 0x68,0x20,0x69,0x73,0x20,0x61,0x20,0x6D,0x65,0x64,0x69,0x6F, - 0x63,0x72,0x65,0x20,0x69,0x6E,0x74,0x65,0x72,0x70,0x6F,0x6C, - 0x61,0x74,0x69,0x6F,0x6E,0x20,0x74,0x79,0x70,0x65,0x2E,0x20, - 0x22,0x53,0x69,0x6E,0x63,0x22,0x20,0x69,0x73,0x20,0x74,0x68, - 0x65,0x20,0x72,0x65,0x63,0x6F,0x6D,0x6D,0x65,0x6E,0x64,0x65, - 0x64,0x50,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x20,0x66,0x6F, - 0x72,0x20,0x74,0x68,0x65,0x20,0x62,0x65,0x73,0x74,0x20,0x61, - 0x75,0x64,0x69,0x6F,0x20,0x71,0x75,0x61,0x6C,0x69,0x74,0x79, - 0x2C,0x20,0x61,0x6C,0x74,0x68,0x6F,0x75,0x67,0x68,0x20,0x69, - 0x74,0x20,0x6D,0x61,0x79,0x20,0x73,0x6F,0x6D,0x65,0x74,0x69, - 0x6D,0x65,0x73,0x20,0x73,0x6F,0x75,0x6E,0x64,0x20,0x74,0x6F, - 0x6F,0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x65,0x64,0x2B,0x61, - 0x6E,0x64,0x20,0x74,0x69,0x6D,0x62,0x72,0x65,0x2D,0x63,0x68, - 0x61,0x6E,0x67,0x69,0x6E,0x67,0x20,0x6F,0x6E,0x20,0x6C,0x6F, - 0x77,0x2D,0x71,0x75,0x61,0x6C,0x69,0x74,0x79,0x20,0x73,0x61, - 0x6D,0x70,0x6C,0x65,0x73,0x2E,0x00,0x1A,0x3E,0x40,0x58,0x30, - 0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x56,0x6F,0x6C,0x75,0x6D, - 0x65,0x20,0x72,0x61,0x6D,0x70,0x69,0x6E,0x67,0x3A,0x0B,0x3E, - 0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x3B,0x45, - 0x6E,0x61,0x62,0x6C,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x61, - 0x6E,0x74,0x69,0x2D,0x63,0x6C,0x69,0x63,0x6B,0x20,0x73,0x79, - 0x73,0x74,0x65,0x6D,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20, - 0x61,0x75,0x64,0x69,0x6F,0x20,0x6D,0x69,0x78,0x65,0x72,0x20, - 0x28,0x46,0x54,0x32,0x2E,0x30,0x38,0x2B,0x29,0x2E,0x3B,0x50, - 0x6C,0x65,0x61,0x73,0x65,0x20,0x6E,0x6F,0x74,0x65,0x20,0x74, - 0x68,0x61,0x74,0x20,0x6F,0x72,0x69,0x67,0x69,0x6E,0x61,0x6C, - 0x20,0x46,0x54,0x32,0x20,0x63,0x61,0x6E,0x27,0x74,0x20,0x6C, - 0x6F,0x61,0x64,0x20,0x74,0x68,0x69,0x73,0x20,0x63,0x6F,0x6E, - 0x66,0x69,0x67,0x20,0x65,0x6E,0x74,0x72,0x79,0x2C,0x0B,0x63, - 0x6C,0x6F,0x6E,0x65,0x20,0x6F,0x6E,0x6C,0x79,0x2E,0x00,0x19, - 0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x41, - 0x6D,0x70,0x6C,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E, - 0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30, - 0x32,0x46,0x41,0x6D,0x70,0x6C,0x69,0x66,0x69,0x65,0x73,0x20, - 0x74,0x68,0x65,0x20,0x76,0x6F,0x6C,0x75,0x6D,0x65,0x20,0x77, - 0x68,0x65,0x6E,0x20,0x6D,0x69,0x78,0x69,0x6E,0x67,0x2E,0x20, - 0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x73,0x65,0x74,0x20,0x74, - 0x68,0x69,0x73,0x20,0x6F,0x6E,0x65,0x20,0x74,0x6F,0x6F,0x20, - 0x68,0x69,0x67,0x68,0x2C,0x20,0x79,0x6F,0x75,0x27,0x6C,0x6C, - 0x3A,0x67,0x65,0x74,0x20,0x64,0x69,0x73,0x74,0x6F,0x72,0x74, - 0x69,0x6F,0x6E,0x2E,0x20,0x33,0x32,0x58,0x20,0x65,0x71,0x75, - 0x61,0x6C,0x73,0x20,0x66,0x75,0x6C,0x6C,0x20,0x61,0x6D,0x70, - 0x6C,0x69,0x74,0x75,0x64,0x65,0x20,0x66,0x6F,0x72,0x20,0x6F, - 0x6E,0x65,0x20,0x63,0x68,0x61,0x6E,0x6E,0x65,0x6C,0x2E,0x00, - 0x1C,0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31, - 0x46,0x72,0x65,0x71,0x75,0x65,0x6E,0x63,0x79,0x20,0x73,0x6C, - 0x69,0x64,0x65,0x73,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30, - 0x40,0x43,0x30,0x30,0x32,0x39,0x4C,0x69,0x6E,0x65,0x61,0x72, - 0x20,0x6D,0x6F,0x64,0x65,0x20,0x6D,0x61,0x6B,0x65,0x73,0x20, - 0x61,0x6C,0x6C,0x20,0x70,0x69,0x74,0x63,0x68,0x20,0x73,0x6C, - 0x69,0x64,0x65,0x73,0x20,0x72,0x75,0x6E,0x20,0x69,0x6E,0x20, - 0x63,0x6F,0x6E,0x73,0x74,0x61,0x6E,0x74,0x20,0x73,0x70,0x65, - 0x65,0x64,0x2C,0x38,0x69,0x6E,0x64,0x65,0x70,0x65,0x6E,0x64, - 0x65,0x6E,0x74,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x63, - 0x75,0x72,0x72,0x65,0x6E,0x74,0x20,0x66,0x72,0x65,0x71,0x75, - 0x65,0x6E,0x63,0x79,0x2E,0x20,0x49,0x66,0x20,0x79,0x6F,0x75, - 0x20,0x73,0x77,0x69,0x74,0x63,0x68,0x20,0x74,0x68,0x69,0x73, - 0x40,0x6F,0x6E,0x65,0x2C,0x20,0x6F,0x6E,0x20,0x61,0x20,0x66, - 0x69,0x6E,0x69,0x73,0x68,0x65,0x64,0x20,0x73,0x6F,0x6E,0x67, - 0x2C,0x20,0x69,0x74,0x20,0x6D,0x69,0x67,0x68,0x74,0x20,0x73, - 0x6F,0x75,0x6E,0x64,0x20,0x73,0x74,0x72,0x61,0x6E,0x67,0x65, - 0x20,0x69,0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x6F,0x6E,0x67, - 0x20,0x75,0x73,0x65,0x73,0x0D,0x70,0x6F,0x72,0x74,0x61,0x6D, - 0x65,0x6E,0x74,0x6F,0x65,0x73,0x2E,0x00,0x20,0x40,0x58,0x30, - 0x32,0x30,0x40,0x43,0x30,0x30,0x31,0x43,0x6F,0x6E,0x66,0x69, - 0x67,0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x2C,0x20,0x4C,0x61, - 0x79,0x6F,0x75,0x74,0x3A,0x01,0x3E,0x29,0x3E,0x40,0x58,0x30, - 0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x50,0x61,0x74,0x74,0x65, - 0x72,0x6E,0x20,0x6C,0x61,0x79,0x6F,0x75,0x74,0x2C,0x20,0x68, - 0x65,0x78,0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x69,0x6E,0x67, - 0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30, - 0x32,0x41,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x75,0x73,0x65, - 0x20,0x70,0x61,0x74,0x74,0x65,0x72,0x6E,0x73,0x20,0x74,0x68, - 0x61,0x74,0x20,0x61,0x72,0x65,0x20,0x6C,0x6F,0x6E,0x67,0x65, - 0x72,0x20,0x74,0x68,0x61,0x6E,0x20,0x39,0x39,0x20,0x6C,0x69, - 0x6E,0x65,0x73,0x2C,0x20,0x79,0x6F,0x75,0x20,0x73,0x68,0x6F, - 0x75,0x6C,0x64,0x20,0x75,0x73,0x65,0x45,0x68,0x65,0x78,0x20, - 0x63,0x6F,0x75,0x6E,0x74,0x69,0x6E,0x67,0x20,0x73,0x69,0x6E, - 0x63,0x65,0x20,0x74,0x68,0x65,0x72,0x65,0x20,0x61,0x72,0x65, - 0x20,0x6F,0x6E,0x6C,0x79,0x20,0x32,0x20,0x64,0x69,0x67,0x69, - 0x74,0x73,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x6C,0x69, - 0x6E,0x65,0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x20,0x63,0x6F, - 0x6C,0x75,0x6D,0x6E,0x2E,0x00,0x12,0x3E,0x40,0x58,0x30,0x34, - 0x30,0x40,0x43,0x30,0x30,0x31,0x53,0x63,0x6F,0x70,0x65,0x73, + 0x65,0x2E,0x3C,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x77,0x61, + 0x6E,0x74,0x20,0x74,0x6F,0x20,0x68,0x61,0x76,0x65,0x20,0x61, + 0x6E,0x20,0x61,0x75,0x74,0x68,0x65,0x6E,0x74,0x69,0x63,0x20, + 0x46,0x54,0x32,0x20,0x73,0x6F,0x75,0x6E,0x64,0x2C,0x20,0x73, + 0x65,0x6C,0x65,0x63,0x74,0x20,0x22,0x6C,0x69,0x6E,0x65,0x61, + 0x72,0x22,0x2E,0x56,0x53,0x69,0x6E,0x63,0x20,0x77,0x69,0x6C, + 0x6C,0x20,0x67,0x69,0x76,0x65,0x20,0x74,0x68,0x65,0x20,0x62, + 0x65,0x73,0x74,0x20,0x69,0x6E,0x74,0x65,0x72,0x70,0x6F,0x6C, + 0x61,0x74,0x69,0x6F,0x6E,0x2C,0x20,0x62,0x75,0x74,0x20,0x69, + 0x74,0x20,0x6D,0x61,0x79,0x20,0x73,0x6F,0x75,0x6E,0x64,0x20, + 0x74,0x6F,0x6F,0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x65,0x64, + 0x20,0x6F,0x6E,0x20,0x6C,0x6F,0x2D,0x66,0x69,0x20,0x73,0x61, + 0x6D,0x70,0x6C,0x65,0x73,0x2E,0x2E,0x54,0x69,0x70,0x3A,0x20, + 0x50,0x6C,0x61,0x79,0x20,0x61,0x72,0x6F,0x75,0x6E,0x64,0x20, + 0x77,0x69,0x74,0x68,0x20,0x74,0x68,0x65,0x20,0x64,0x69,0x66, + 0x66,0x65,0x72,0x65,0x6E,0x74,0x20,0x6F,0x70,0x74,0x69,0x6F, + 0x6E,0x73,0x2E,0x2E,0x2E,0x00,0x1A,0x3E,0x40,0x58,0x30,0x34, + 0x30,0x40,0x43,0x30,0x30,0x31,0x56,0x6F,0x6C,0x75,0x6D,0x65, + 0x20,0x72,0x61,0x6D,0x70,0x69,0x6E,0x67,0x3A,0x0B,0x3E,0x40, + 0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x3B,0x45,0x6E, + 0x61,0x62,0x6C,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x61,0x6E, + 0x74,0x69,0x2D,0x63,0x6C,0x69,0x63,0x6B,0x20,0x73,0x79,0x73, + 0x74,0x65,0x6D,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x61, + 0x75,0x64,0x69,0x6F,0x20,0x6D,0x69,0x78,0x65,0x72,0x20,0x28, + 0x46,0x54,0x32,0x2E,0x30,0x38,0x2B,0x29,0x2E,0x3B,0x50,0x6C, + 0x65,0x61,0x73,0x65,0x20,0x6E,0x6F,0x74,0x65,0x20,0x74,0x68, + 0x61,0x74,0x20,0x6F,0x72,0x69,0x67,0x69,0x6E,0x61,0x6C,0x20, + 0x46,0x54,0x32,0x20,0x63,0x61,0x6E,0x27,0x74,0x20,0x6C,0x6F, + 0x61,0x64,0x20,0x74,0x68,0x69,0x73,0x20,0x63,0x6F,0x6E,0x66, + 0x69,0x67,0x20,0x65,0x6E,0x74,0x72,0x79,0x2C,0x0B,0x63,0x6C, + 0x6F,0x6E,0x65,0x20,0x6F,0x6E,0x6C,0x79,0x2E,0x00,0x19,0x3E, + 0x40,0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x41,0x6D, + 0x70,0x6C,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x3A, + 0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32, + 0x46,0x41,0x6D,0x70,0x6C,0x69,0x66,0x69,0x65,0x73,0x20,0x74, + 0x68,0x65,0x20,0x76,0x6F,0x6C,0x75,0x6D,0x65,0x20,0x77,0x68, + 0x65,0x6E,0x20,0x6D,0x69,0x78,0x69,0x6E,0x67,0x2E,0x20,0x49, + 0x66,0x20,0x79,0x6F,0x75,0x20,0x73,0x65,0x74,0x20,0x74,0x68, + 0x69,0x73,0x20,0x6F,0x6E,0x65,0x20,0x74,0x6F,0x6F,0x20,0x68, + 0x69,0x67,0x68,0x2C,0x20,0x79,0x6F,0x75,0x27,0x6C,0x6C,0x3A, + 0x67,0x65,0x74,0x20,0x64,0x69,0x73,0x74,0x6F,0x72,0x74,0x69, + 0x6F,0x6E,0x2E,0x20,0x33,0x32,0x58,0x20,0x65,0x71,0x75,0x61, + 0x6C,0x73,0x20,0x66,0x75,0x6C,0x6C,0x20,0x61,0x6D,0x70,0x6C, + 0x69,0x74,0x75,0x64,0x65,0x20,0x66,0x6F,0x72,0x20,0x6F,0x6E, + 0x65,0x20,0x63,0x68,0x61,0x6E,0x6E,0x65,0x6C,0x2E,0x00,0x1C, + 0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x46, + 0x72,0x65,0x71,0x75,0x65,0x6E,0x63,0x79,0x20,0x73,0x6C,0x69, + 0x64,0x65,0x73,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40, + 0x43,0x30,0x30,0x32,0x39,0x4C,0x69,0x6E,0x65,0x61,0x72,0x20, + 0x6D,0x6F,0x64,0x65,0x20,0x6D,0x61,0x6B,0x65,0x73,0x20,0x61, + 0x6C,0x6C,0x20,0x70,0x69,0x74,0x63,0x68,0x20,0x73,0x6C,0x69, + 0x64,0x65,0x73,0x20,0x72,0x75,0x6E,0x20,0x69,0x6E,0x20,0x63, + 0x6F,0x6E,0x73,0x74,0x61,0x6E,0x74,0x20,0x73,0x70,0x65,0x65, + 0x64,0x2C,0x38,0x69,0x6E,0x64,0x65,0x70,0x65,0x6E,0x64,0x65, + 0x6E,0x74,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x63,0x75, + 0x72,0x72,0x65,0x6E,0x74,0x20,0x66,0x72,0x65,0x71,0x75,0x65, + 0x6E,0x63,0x79,0x2E,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x20, + 0x73,0x77,0x69,0x74,0x63,0x68,0x20,0x74,0x68,0x69,0x73,0x40, + 0x6F,0x6E,0x65,0x2C,0x20,0x6F,0x6E,0x20,0x61,0x20,0x66,0x69, + 0x6E,0x69,0x73,0x68,0x65,0x64,0x20,0x73,0x6F,0x6E,0x67,0x2C, + 0x20,0x69,0x74,0x20,0x6D,0x69,0x67,0x68,0x74,0x20,0x73,0x6F, + 0x75,0x6E,0x64,0x20,0x73,0x74,0x72,0x61,0x6E,0x67,0x65,0x20, + 0x69,0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x6F,0x6E,0x67,0x20, + 0x75,0x73,0x65,0x73,0x0D,0x70,0x6F,0x72,0x74,0x61,0x6D,0x65, + 0x6E,0x74,0x6F,0x65,0x73,0x2E,0x00,0x20,0x40,0x58,0x30,0x32, + 0x30,0x40,0x43,0x30,0x30,0x31,0x43,0x6F,0x6E,0x66,0x69,0x67, + 0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x2C,0x20,0x4C,0x61,0x79, + 0x6F,0x75,0x74,0x3A,0x01,0x3E,0x29,0x3E,0x40,0x58,0x30,0x34, + 0x30,0x40,0x43,0x30,0x30,0x31,0x50,0x61,0x74,0x74,0x65,0x72, + 0x6E,0x20,0x6C,0x61,0x79,0x6F,0x75,0x74,0x2C,0x20,0x68,0x65, + 0x78,0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x69,0x6E,0x67,0x3A, + 0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32, + 0x41,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x75,0x73,0x65,0x20, + 0x70,0x61,0x74,0x74,0x65,0x72,0x6E,0x73,0x20,0x74,0x68,0x61, + 0x74,0x20,0x61,0x72,0x65,0x20,0x6C,0x6F,0x6E,0x67,0x65,0x72, + 0x20,0x74,0x68,0x61,0x6E,0x20,0x39,0x39,0x20,0x6C,0x69,0x6E, + 0x65,0x73,0x2C,0x20,0x79,0x6F,0x75,0x20,0x73,0x68,0x6F,0x75, + 0x6C,0x64,0x20,0x75,0x73,0x65,0x45,0x68,0x65,0x78,0x20,0x63, + 0x6F,0x75,0x6E,0x74,0x69,0x6E,0x67,0x20,0x73,0x69,0x6E,0x63, + 0x65,0x20,0x74,0x68,0x65,0x72,0x65,0x20,0x61,0x72,0x65,0x20, + 0x6F,0x6E,0x6C,0x79,0x20,0x32,0x20,0x64,0x69,0x67,0x69,0x74, + 0x73,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x6C,0x69,0x6E, + 0x65,0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x20,0x63,0x6F,0x6C, + 0x75,0x6D,0x6E,0x2E,0x00,0x12,0x3E,0x40,0x58,0x30,0x34,0x30, + 0x40,0x43,0x30,0x30,0x31,0x53,0x63,0x6F,0x70,0x65,0x73,0x3A, + 0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32, + 0x43,0x22,0x53,0x74,0x64,0x2E,0x22,0x20,0x28,0x73,0x74,0x61, + 0x6E,0x64,0x61,0x72,0x64,0x29,0x20,0x77,0x69,0x6C,0x6C,0x20, + 0x73,0x68,0x6F,0x77,0x20,0x74,0x68,0x65,0x20,0x73,0x61,0x6D, + 0x70,0x6C,0x65,0x20,0x70,0x6F,0x69,0x6E,0x74,0x73,0x20,0x61, + 0x73,0x20,0x70,0x69,0x78,0x65,0x6C,0x73,0x20,0x28,0x6C,0x69, + 0x6B,0x65,0x20,0x46,0x54,0x32,0x29,0x2E,0x3D,0x22,0x4C,0x69, + 0x6E,0x65,0x64,0x22,0x20,0x77,0x69,0x6C,0x6C,0x20,0x64,0x72, + 0x61,0x77,0x20,0x69,0x6E,0x74,0x65,0x72,0x70,0x6F,0x6C,0x61, + 0x74,0x65,0x64,0x20,0x73,0x61,0x6D,0x70,0x6C,0x65,0x73,0x20, + 0x28,0x6C,0x69,0x6E,0x65,0x61,0x72,0x20,0x69,0x6E,0x74,0x65, + 0x72,0x70,0x6F,0x6C,0x61,0x74,0x69,0x6F,0x6E,0x2E,0x00,0x27, + 0x40,0x58,0x30,0x32,0x30,0x40,0x43,0x30,0x30,0x31,0x43,0x6F, + 0x6E,0x66,0x69,0x67,0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x2C, + 0x20,0x4D,0x69,0x73,0x63,0x65,0x6C,0x6C,0x61,0x6E,0x65,0x6F, + 0x75,0x73,0x3A,0x01,0x3E,0x15,0x3E,0x40,0x58,0x30,0x34,0x30, + 0x40,0x43,0x30,0x30,0x31,0x56,0x53,0x79,0x6E,0x63,0x20,0x6F, + 0x66,0x66,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43, + 0x30,0x30,0x32,0x3F,0x54,0x65,0x6C,0x6C,0x73,0x20,0x74,0x68, + 0x65,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x20,0x74,0x6F, + 0x20,0x6E,0x6F,0x74,0x20,0x75,0x73,0x65,0x20,0x56,0x53,0x79, + 0x6E,0x63,0x20,0x66,0x6F,0x72,0x20,0x76,0x69,0x64,0x65,0x6F, + 0x2E,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x72,0x20,0x6D,0x6F, + 0x6E,0x69,0x74,0x6F,0x72,0x27,0x73,0x40,0x72,0x65,0x66,0x72, + 0x65,0x73,0x68,0x20,0x72,0x61,0x74,0x65,0x20,0x69,0x73,0x20, + 0x6E,0x6F,0x74,0x20,0x36,0x30,0x48,0x7A,0x20,0x28,0x6F,0x72, + 0x20,0x35,0x39,0x48,0x7A,0x29,0x2C,0x20,0x74,0x68,0x65,0x6E, + 0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x69,0x73,0x20,0x61,0x6C, + 0x77,0x61,0x79,0x73,0x20,0x6F,0x66,0x66,0x20,0x66,0x6F,0x72, + 0x45,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6F,0x67,0x72,0x61, + 0x6D,0x2E,0x20,0x4E,0x6F,0x74,0x20,0x68,0x61,0x76,0x69,0x6E, + 0x67,0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x77,0x69,0x6C,0x6C, + 0x20,0x72,0x65,0x73,0x75,0x6C,0x74,0x20,0x69,0x6E,0x20,0x6C, + 0x65,0x73,0x73,0x20,0x69,0x6E,0x70,0x75,0x74,0x2F,0x76,0x69, + 0x64,0x65,0x6F,0x20,0x64,0x65,0x6C,0x61,0x79,0x2C,0x1E,0x62, + 0x75,0x74,0x20,0x61,0x6C,0x73,0x6F,0x20,0x70,0x6F,0x74,0x65, + 0x6E,0x74,0x69,0x61,0x6C,0x20,0x73,0x74,0x75,0x74,0x74,0x65, + 0x72,0x69,0x6E,0x67,0x2E,0x00,0x15,0x3E,0x40,0x58,0x30,0x34, + 0x30,0x40,0x43,0x30,0x30,0x31,0x53,0x74,0x72,0x65,0x74,0x63, + 0x68,0x65,0x64,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40, + 0x43,0x30,0x30,0x32,0x4A,0x4D,0x61,0x6B,0x65,0x73,0x20,0x66, + 0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20,0x6D,0x6F, + 0x64,0x65,0x20,0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74,0x65,0x6C, + 0x79,0x20,0x73,0x74,0x72,0x65,0x74,0x63,0x68,0x20,0x6F,0x75, + 0x74,0x20,0x74,0x68,0x65,0x20,0x69,0x6D,0x61,0x67,0x65,0x2E, + 0x20,0x54,0x68,0x69,0x73,0x20,0x63,0x61,0x6E,0x20,0x72,0x65, + 0x73,0x75,0x6C,0x74,0x20,0x69,0x6E,0x4E,0x61,0x6C,0x69,0x61, + 0x73,0x69,0x6E,0x67,0x20,0x28,0x75,0x6E,0x65,0x76,0x65,0x6E, + 0x20,0x70,0x69,0x78,0x65,0x6C,0x20,0x77,0x69,0x64,0x74,0x68, + 0x73,0x29,0x20,0x69,0x66,0x20,0x74,0x68,0x65,0x20,0x61,0x73, + 0x70,0x65,0x63,0x74,0x20,0x72,0x61,0x74,0x69,0x6F,0x20,0x6F, + 0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x63,0x72,0x65,0x65,0x6E, + 0x20,0x69,0x73,0x20,0x6E,0x6F,0x74,0x20,0x31,0x36,0x3A,0x31, + 0x30,0x2E,0x52,0x54,0x68,0x65,0x20,0x22,0x50,0x69,0x78,0x65, + 0x6C,0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x22,0x20,0x73,0x65, + 0x74,0x74,0x69,0x6E,0x67,0x20,0x63,0x61,0x6E,0x20,0x68,0x65, + 0x6C,0x70,0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x68,0x69,0x73, + 0x2C,0x20,0x62,0x75,0x74,0x20,0x69,0x74,0x20,0x6D,0x61,0x6B, + 0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x69,0x6D,0x61,0x67,0x65, + 0x20,0x6C,0x6F,0x6F,0x6B,0x20,0x62,0x6C,0x75,0x72,0x72,0x79, + 0x2E,0x01,0x20,0x18,0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43, + 0x30,0x30,0x31,0x50,0x69,0x78,0x65,0x6C,0x20,0x66,0x69,0x6C, + 0x74,0x65,0x72,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40, + 0x43,0x30,0x30,0x32,0x52,0x41,0x70,0x70,0x6C,0x69,0x65,0x73, + 0x20,0x61,0x6E,0x20,0x61,0x6E,0x74,0x69,0x2D,0x61,0x6C,0x69, + 0x61,0x73,0x69,0x6E,0x67,0x20,0x73,0x75,0x62,0x70,0x69,0x78, + 0x65,0x6C,0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x20,0x74,0x68, + 0x61,0x74,0x20,0x69,0x73,0x20,0x75,0x73,0x65,0x64,0x20,0x77, + 0x68,0x65,0x6E,0x20,0x74,0x68,0x65,0x20,0x77,0x69,0x6E,0x64, + 0x6F,0x77,0x20,0x69,0x73,0x20,0x75,0x70,0x73,0x63,0x61,0x6C, + 0x65,0x64,0x2E,0x3B,0x50,0x6C,0x65,0x61,0x73,0x65,0x20,0x6B, + 0x65,0x65,0x70,0x20,0x69,0x6E,0x20,0x6D,0x69,0x6E,0x64,0x20, + 0x74,0x68,0x61,0x74,0x20,0x74,0x68,0x69,0x73,0x20,0x77,0x69, + 0x6C,0x6C,0x20,0x6D,0x61,0x6B,0x65,0x20,0x70,0x69,0x78,0x65, + 0x6C,0x73,0x20,0x6C,0x6F,0x6F,0x6B,0x20,0x62,0x6C,0x75,0x72, + 0x72,0x79,0x2E,0x00,0x23,0x40,0x58,0x30,0x32,0x30,0x40,0x43, + 0x30,0x30,0x31,0x41,0x64,0x76,0x61,0x6E,0x63,0x65,0x64,0x20, + 0x65,0x64,0x69,0x74,0x20,0x66,0x75,0x6E,0x63,0x74,0x69,0x6F, + 0x6E,0x73,0x3A,0x20,0x01,0x3E,0x1E,0x3E,0x40,0x58,0x30,0x34, + 0x30,0x40,0x43,0x30,0x30,0x31,0x43,0x6F,0x70,0x79,0x2F,0x50, + 0x61,0x73,0x74,0x65,0x20,0x6D,0x61,0x73,0x6B,0x69,0x6E,0x67, 0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30, - 0x32,0x43,0x22,0x53,0x74,0x64,0x2E,0x22,0x20,0x28,0x73,0x74, - 0x61,0x6E,0x64,0x61,0x72,0x64,0x29,0x20,0x77,0x69,0x6C,0x6C, - 0x20,0x73,0x68,0x6F,0x77,0x20,0x74,0x68,0x65,0x20,0x73,0x61, - 0x6D,0x70,0x6C,0x65,0x20,0x70,0x6F,0x69,0x6E,0x74,0x73,0x20, - 0x61,0x73,0x20,0x70,0x69,0x78,0x65,0x6C,0x73,0x20,0x28,0x6C, - 0x69,0x6B,0x65,0x20,0x46,0x54,0x32,0x29,0x2E,0x3D,0x22,0x4C, - 0x69,0x6E,0x65,0x64,0x22,0x20,0x77,0x69,0x6C,0x6C,0x20,0x64, - 0x72,0x61,0x77,0x20,0x69,0x6E,0x74,0x65,0x72,0x70,0x6F,0x6C, - 0x61,0x74,0x65,0x64,0x20,0x73,0x61,0x6D,0x70,0x6C,0x65,0x73, - 0x20,0x28,0x6C,0x69,0x6E,0x65,0x61,0x72,0x20,0x69,0x6E,0x74, - 0x65,0x72,0x70,0x6F,0x6C,0x61,0x74,0x69,0x6F,0x6E,0x2E,0x00, - 0x27,0x40,0x58,0x30,0x32,0x30,0x40,0x43,0x30,0x30,0x31,0x43, - 0x6F,0x6E,0x66,0x69,0x67,0x75,0x72,0x61,0x74,0x69,0x6F,0x6E, - 0x2C,0x20,0x4D,0x69,0x73,0x63,0x65,0x6C,0x6C,0x61,0x6E,0x65, - 0x6F,0x75,0x73,0x3A,0x01,0x3E,0x15,0x3E,0x40,0x58,0x30,0x34, - 0x30,0x40,0x43,0x30,0x30,0x31,0x56,0x53,0x79,0x6E,0x63,0x20, - 0x6F,0x66,0x66,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40, - 0x43,0x30,0x30,0x32,0x3F,0x54,0x65,0x6C,0x6C,0x73,0x20,0x74, - 0x68,0x65,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x20,0x74, - 0x6F,0x20,0x6E,0x6F,0x74,0x20,0x75,0x73,0x65,0x20,0x56,0x53, - 0x79,0x6E,0x63,0x20,0x66,0x6F,0x72,0x20,0x76,0x69,0x64,0x65, - 0x6F,0x2E,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x72,0x20,0x6D, - 0x6F,0x6E,0x69,0x74,0x6F,0x72,0x27,0x73,0x40,0x72,0x65,0x66, - 0x72,0x65,0x73,0x68,0x20,0x72,0x61,0x74,0x65,0x20,0x69,0x73, - 0x20,0x6E,0x6F,0x74,0x20,0x36,0x30,0x48,0x7A,0x20,0x28,0x6F, - 0x72,0x20,0x35,0x39,0x48,0x7A,0x29,0x2C,0x20,0x74,0x68,0x65, - 0x6E,0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x69,0x73,0x20,0x61, - 0x6C,0x77,0x61,0x79,0x73,0x20,0x6F,0x66,0x66,0x20,0x66,0x6F, - 0x72,0x45,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6F,0x67,0x72, - 0x61,0x6D,0x2E,0x20,0x4E,0x6F,0x74,0x20,0x68,0x61,0x76,0x69, - 0x6E,0x67,0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x77,0x69,0x6C, - 0x6C,0x20,0x72,0x65,0x73,0x75,0x6C,0x74,0x20,0x69,0x6E,0x20, - 0x6C,0x65,0x73,0x73,0x20,0x69,0x6E,0x70,0x75,0x74,0x2F,0x76, - 0x69,0x64,0x65,0x6F,0x20,0x64,0x65,0x6C,0x61,0x79,0x2C,0x1E, - 0x62,0x75,0x74,0x20,0x61,0x6C,0x73,0x6F,0x20,0x70,0x6F,0x74, - 0x65,0x6E,0x74,0x69,0x61,0x6C,0x20,0x73,0x74,0x75,0x74,0x74, - 0x65,0x72,0x69,0x6E,0x67,0x2E,0x00,0x15,0x3E,0x40,0x58,0x30, - 0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x53,0x74,0x72,0x65,0x74, - 0x63,0x68,0x65,0x64,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30, - 0x40,0x43,0x30,0x30,0x32,0x4A,0x4D,0x61,0x6B,0x65,0x73,0x20, - 0x66,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20,0x6D, - 0x6F,0x64,0x65,0x20,0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74,0x65, - 0x6C,0x79,0x20,0x73,0x74,0x72,0x65,0x74,0x63,0x68,0x20,0x6F, - 0x75,0x74,0x20,0x74,0x68,0x65,0x20,0x69,0x6D,0x61,0x67,0x65, - 0x2E,0x20,0x54,0x68,0x69,0x73,0x20,0x63,0x61,0x6E,0x20,0x72, - 0x65,0x73,0x75,0x6C,0x74,0x20,0x69,0x6E,0x4E,0x61,0x6C,0x69, - 0x61,0x73,0x69,0x6E,0x67,0x20,0x28,0x75,0x6E,0x65,0x76,0x65, - 0x6E,0x20,0x70,0x69,0x78,0x65,0x6C,0x20,0x77,0x69,0x64,0x74, - 0x68,0x73,0x29,0x20,0x69,0x66,0x20,0x74,0x68,0x65,0x20,0x61, - 0x73,0x70,0x65,0x63,0x74,0x20,0x72,0x61,0x74,0x69,0x6F,0x20, - 0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x63,0x72,0x65,0x65, - 0x6E,0x20,0x69,0x73,0x20,0x6E,0x6F,0x74,0x20,0x31,0x36,0x3A, - 0x31,0x30,0x2E,0x52,0x54,0x68,0x65,0x20,0x22,0x50,0x69,0x78, - 0x65,0x6C,0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x22,0x20,0x73, - 0x65,0x74,0x74,0x69,0x6E,0x67,0x20,0x63,0x61,0x6E,0x20,0x68, - 0x65,0x6C,0x70,0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x68,0x69, - 0x73,0x2C,0x20,0x62,0x75,0x74,0x20,0x69,0x74,0x20,0x6D,0x61, - 0x6B,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x69,0x6D,0x61,0x67, - 0x65,0x20,0x6C,0x6F,0x6F,0x6B,0x20,0x62,0x6C,0x75,0x72,0x72, - 0x79,0x2E,0x01,0x20,0x18,0x3E,0x40,0x58,0x30,0x34,0x30,0x40, - 0x43,0x30,0x30,0x31,0x50,0x69,0x78,0x65,0x6C,0x20,0x66,0x69, - 0x6C,0x74,0x65,0x72,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30, - 0x40,0x43,0x30,0x30,0x32,0x52,0x41,0x70,0x70,0x6C,0x69,0x65, - 0x73,0x20,0x61,0x6E,0x20,0x61,0x6E,0x74,0x69,0x2D,0x61,0x6C, - 0x69,0x61,0x73,0x69,0x6E,0x67,0x20,0x73,0x75,0x62,0x70,0x69, - 0x78,0x65,0x6C,0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x20,0x74, - 0x68,0x61,0x74,0x20,0x69,0x73,0x20,0x75,0x73,0x65,0x64,0x20, - 0x77,0x68,0x65,0x6E,0x20,0x74,0x68,0x65,0x20,0x77,0x69,0x6E, - 0x64,0x6F,0x77,0x20,0x69,0x73,0x20,0x75,0x70,0x73,0x63,0x61, - 0x6C,0x65,0x64,0x2E,0x3B,0x50,0x6C,0x65,0x61,0x73,0x65,0x20, - 0x6B,0x65,0x65,0x70,0x20,0x69,0x6E,0x20,0x6D,0x69,0x6E,0x64, - 0x20,0x74,0x68,0x61,0x74,0x20,0x74,0x68,0x69,0x73,0x20,0x77, - 0x69,0x6C,0x6C,0x20,0x6D,0x61,0x6B,0x65,0x20,0x70,0x69,0x78, - 0x65,0x6C,0x73,0x20,0x6C,0x6F,0x6F,0x6B,0x20,0x62,0x6C,0x75, - 0x72,0x72,0x79,0x2E,0x00,0x23,0x40,0x58,0x30,0x32,0x30,0x40, - 0x43,0x30,0x30,0x31,0x41,0x64,0x76,0x61,0x6E,0x63,0x65,0x64, - 0x20,0x65,0x64,0x69,0x74,0x20,0x66,0x75,0x6E,0x63,0x74,0x69, - 0x6F,0x6E,0x73,0x3A,0x20,0x01,0x3E,0x1E,0x3E,0x40,0x58,0x30, - 0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x43,0x6F,0x70,0x79,0x2F, - 0x50,0x61,0x73,0x74,0x65,0x20,0x6D,0x61,0x73,0x6B,0x69,0x6E, - 0x67,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30, - 0x30,0x32,0x37,0x54,0x68,0x65,0x20,0x6D,0x61,0x73,0x6B,0x69, - 0x6E,0x67,0x20,0x69,0x73,0x20,0x75,0x73,0x65,0x64,0x20,0x66, - 0x6F,0x72,0x20,0x63,0x6F,0x70,0x79,0x69,0x6E,0x67,0x2F,0x70, - 0x61,0x73,0x74,0x69,0x6E,0x67,0x20,0x6F,0x6E,0x6C,0x79,0x20, - 0x70,0x61,0x72,0x74,0x73,0x20,0x6F,0x66,0x20,0x61,0x46,0x22, - 0x6E,0x6F,0x74,0x65,0x2D,0x63,0x65,0x6C,0x6C,0x22,0x2E,0x20, - 0x54,0x68,0x65,0x20,0x64,0x69,0x66,0x66,0x65,0x72,0x65,0x6E, - 0x74,0x20,0x70,0x61,0x72,0x74,0x73,0x20,0x6F,0x66,0x20,0x61, - 0x20,0x22,0x6E,0x6F,0x74,0x65,0x2D,0x63,0x65,0x6C,0x6C,0x22, - 0x20,0x69,0x73,0x20,0x4E,0x6F,0x74,0x65,0x2C,0x20,0x49,0x6E, - 0x73,0x74,0x72,0x2E,0x20,0x6E,0x72,0x2E,0x2C,0x20,0x56,0x6F, - 0x6C,0x75,0x6D,0x65,0x2C,0x20,0x45,0x66,0x66,0x65,0x63,0x74, - 0x20,0x6E,0x72,0x20,0x26,0x20,0x45,0x66,0x66,0x65,0x63,0x74, - 0x20,0x64,0x61,0x74,0x61,0x2E,0x34,0x3E,0x41,0x73,0x20,0x79, - 0x6F,0x75,0x20,0x63,0x61,0x6E,0x20,0x73,0x65,0x65,0x20,0x69, - 0x6E,0x20,0x74,0x68,0x65,0x20,0x77,0x69,0x6E,0x64,0x6F,0x77, - 0x20,0x74,0x68,0x65,0x72,0x65,0x20,0x61,0x72,0x65,0x20,0x33, - 0x20,0x63,0x6F,0x6C,0x75,0x6D,0x6E,0x73,0x20,0x6F,0x66,0x3D, - 0x22,0x65,0x6E,0x61,0x62,0x6C,0x65,0x2F,0x64,0x69,0x73,0x61, - 0x62,0x6C,0x65,0x20,0x62,0x75,0x74,0x74,0x6F,0x6E,0x73,0x22, - 0x20,0x77,0x68,0x69,0x63,0x68,0x20,0x68,0x61,0x73,0x20,0x74, - 0x68,0x65,0x20,0x6C,0x65,0x74,0x74,0x65,0x72,0x73,0x20,0x43, - 0x2C,0x50,0x20,0x26,0x20,0x54,0x20,0x61,0x62,0x6F,0x76,0x65, - 0x2E,0x45,0x3E,0x43,0x20,0x6D,0x65,0x61,0x6E,0x73,0x20,0x63, - 0x6F,0x70,0x79,0x2C,0x20,0x69,0x74,0x20,0x63,0x6F,0x6E,0x74, - 0x72,0x6F,0x6C,0x73,0x20,0x77,0x68,0x69,0x63,0x68,0x20,0x70, - 0x61,0x72,0x74,0x73,0x20,0x74,0x68,0x61,0x74,0x20,0x67,0x6F, - 0x65,0x73,0x20,0x69,0x6E,0x74,0x6F,0x20,0x74,0x68,0x65,0x20, - 0x63,0x6F,0x70,0x79,0x62,0x75,0x66,0x66,0x65,0x72,0x2E,0x3E, - 0x3E,0x50,0x20,0x6D,0x65,0x61,0x6E,0x73,0x20,0x70,0x61,0x73, - 0x74,0x65,0x20,0x61,0x6E,0x64,0x20,0x63,0x6F,0x6E,0x74,0x72, + 0x32,0x37,0x54,0x68,0x65,0x20,0x6D,0x61,0x73,0x6B,0x69,0x6E, + 0x67,0x20,0x69,0x73,0x20,0x75,0x73,0x65,0x64,0x20,0x66,0x6F, + 0x72,0x20,0x63,0x6F,0x70,0x79,0x69,0x6E,0x67,0x2F,0x70,0x61, + 0x73,0x74,0x69,0x6E,0x67,0x20,0x6F,0x6E,0x6C,0x79,0x20,0x70, + 0x61,0x72,0x74,0x73,0x20,0x6F,0x66,0x20,0x61,0x46,0x22,0x6E, + 0x6F,0x74,0x65,0x2D,0x63,0x65,0x6C,0x6C,0x22,0x2E,0x20,0x54, + 0x68,0x65,0x20,0x64,0x69,0x66,0x66,0x65,0x72,0x65,0x6E,0x74, + 0x20,0x70,0x61,0x72,0x74,0x73,0x20,0x6F,0x66,0x20,0x61,0x20, + 0x22,0x6E,0x6F,0x74,0x65,0x2D,0x63,0x65,0x6C,0x6C,0x22,0x20, + 0x69,0x73,0x20,0x4E,0x6F,0x74,0x65,0x2C,0x20,0x49,0x6E,0x73, + 0x74,0x72,0x2E,0x20,0x6E,0x72,0x2E,0x2C,0x20,0x56,0x6F,0x6C, + 0x75,0x6D,0x65,0x2C,0x20,0x45,0x66,0x66,0x65,0x63,0x74,0x20, + 0x6E,0x72,0x20,0x26,0x20,0x45,0x66,0x66,0x65,0x63,0x74,0x20, + 0x64,0x61,0x74,0x61,0x2E,0x34,0x3E,0x41,0x73,0x20,0x79,0x6F, + 0x75,0x20,0x63,0x61,0x6E,0x20,0x73,0x65,0x65,0x20,0x69,0x6E, + 0x20,0x74,0x68,0x65,0x20,0x77,0x69,0x6E,0x64,0x6F,0x77,0x20, + 0x74,0x68,0x65,0x72,0x65,0x20,0x61,0x72,0x65,0x20,0x33,0x20, + 0x63,0x6F,0x6C,0x75,0x6D,0x6E,0x73,0x20,0x6F,0x66,0x3D,0x22, + 0x65,0x6E,0x61,0x62,0x6C,0x65,0x2F,0x64,0x69,0x73,0x61,0x62, + 0x6C,0x65,0x20,0x62,0x75,0x74,0x74,0x6F,0x6E,0x73,0x22,0x20, + 0x77,0x68,0x69,0x63,0x68,0x20,0x68,0x61,0x73,0x20,0x74,0x68, + 0x65,0x20,0x6C,0x65,0x74,0x74,0x65,0x72,0x73,0x20,0x43,0x2C, + 0x50,0x20,0x26,0x20,0x54,0x20,0x61,0x62,0x6F,0x76,0x65,0x2E, + 0x45,0x3E,0x43,0x20,0x6D,0x65,0x61,0x6E,0x73,0x20,0x63,0x6F, + 0x70,0x79,0x2C,0x20,0x69,0x74,0x20,0x63,0x6F,0x6E,0x74,0x72, 0x6F,0x6C,0x73,0x20,0x77,0x68,0x69,0x63,0x68,0x20,0x70,0x61, 0x72,0x74,0x73,0x20,0x74,0x68,0x61,0x74,0x20,0x67,0x6F,0x65, - 0x73,0x20,0x6F,0x75,0x74,0x20,0x66,0x72,0x6F,0x6D,0x20,0x74, - 0x68,0x65,0x0B,0x63,0x6F,0x70,0x79,0x62,0x75,0x66,0x66,0x65, - 0x72,0x2E,0x45,0x3E,0x54,0x20,0x6D,0x65,0x61,0x6E,0x73,0x20, - 0x74,0x72,0x61,0x6E,0x73,0x70,0x61,0x72,0x65,0x6E,0x63,0x79, - 0x2E,0x20,0x49,0x66,0x20,0x69,0x74,0x27,0x73,0x20,0x65,0x6E, - 0x61,0x62,0x6C,0x65,0x64,0x2C,0x20,0x74,0x68,0x65,0x20,0x70, - 0x61,0x73,0x74,0x69,0x6E,0x67,0x20,0x64,0x6F,0x65,0x73,0x6E, - 0x27,0x74,0x20,0x6F,0x76,0x65,0x72,0x77,0x72,0x69,0x74,0x65, - 0x3D,0x64,0x61,0x74,0x61,0x20,0x77,0x69,0x74,0x68,0x20,0x6E, - 0x69,0x6C,0x2D,0x69,0x6E,0x66,0x6F,0x72,0x6D,0x61,0x74,0x69, - 0x6F,0x6E,0x2C,0x20,0x6F,0x6E,0x6C,0x79,0x20,0x77,0x69,0x74, - 0x68,0x20,0x61,0x20,0x6E,0x6F,0x74,0x65,0x20,0x6F,0x72,0x20, - 0x61,0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x20,0x3C,0x3E,0x20, - 0x30,0x2E,0x01,0x3E,0x40,0x3E,0x54,0x68,0x65,0x20,0x63,0x75, - 0x74,0x20,0x66,0x75,0x6E,0x63,0x74,0x69,0x6F,0x6E,0x73,0x20, - 0x77,0x6F,0x72,0x6B,0x73,0x20,0x6C,0x69,0x6B,0x65,0x20,0x70, - 0x61,0x73,0x74,0x69,0x6E,0x67,0x20,0x77,0x69,0x74,0x68,0x20, - 0x7A,0x65,0x72,0x6F,0x2D,0x64,0x61,0x74,0x61,0x2E,0x20,0x54, - 0x68,0x69,0x73,0x20,0x6D,0x65,0x61,0x6E,0x73,0x3B,0x74,0x68, - 0x61,0x74,0x20,0x74,0x68,0x65,0x20,0x63,0x75,0x74,0x74,0x69, - 0x6E,0x67,0x20,0x69,0x73,0x20,0x63,0x6F,0x6E,0x74,0x72,0x6F, - 0x6C,0x6C,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x50,0x2D, - 0x63,0x6F,0x6C,0x75,0x6D,0x6E,0x20,0x28,0x6F,0x72,0x20,0x54, - 0x2D,0x63,0x6F,0x6C,0x75,0x6D,0x6E,0x29,0x2E,0x3C,0x3E,0x57, - 0x68,0x65,0x6E,0x20,0x79,0x6F,0x75,0x20,0x63,0x6F,0x70,0x79, - 0x20,0x64,0x61,0x74,0x61,0x20,0x77,0x69,0x74,0x68,0x20,0x6D, - 0x61,0x73,0x6B,0x69,0x6E,0x67,0x2C,0x20,0x74,0x68,0x65,0x20, - 0x64,0x69,0x73,0x61,0x62,0x6C,0x65,0x64,0x20,0x70,0x61,0x72, - 0x74,0x73,0x20,0x61,0x72,0x65,0x20,0x6E,0x6F,0x74,0x43,0x63, - 0x6C,0x65,0x61,0x72,0x65,0x64,0x20,0x69,0x6E,0x20,0x74,0x68, - 0x65,0x20,0x63,0x6F,0x70,0x79,0x62,0x75,0x66,0x66,0x65,0x72, - 0x2E,0x20,0x28,0x4D,0x61,0x6B,0x69,0x6E,0x67,0x20,0x69,0x74, - 0x20,0x70,0x6F,0x73,0x73,0x69,0x62,0x6C,0x65,0x20,0x74,0x6F, - 0x20,0x63,0x6F,0x6C,0x6C,0x65,0x63,0x74,0x20,0x64,0x61,0x74, - 0x61,0x20,0x66,0x72,0x6F,0x6D,0x27,0x73,0x65,0x76,0x65,0x72, - 0x61,0x6C,0x20,0x6C,0x6F,0x63,0x61,0x74,0x69,0x6F,0x6E,0x73, - 0x20,0x69,0x6E,0x74,0x6F,0x20,0x74,0x68,0x65,0x20,0x63,0x6F, - 0x70,0x79,0x62,0x75,0x66,0x66,0x65,0x72,0x2E,0x29,0x00,0x03, - 0x45,0x4E,0x44,0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x4C,0x3B,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x0E,0x40,0x4C,0x50,0x72,0x6F,0x62,0x6C,0x65,0x6D,0x73, - 0x2F,0x46,0x41,0x51,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x2A, - 0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x48,0x6F,0x77, - 0x20,0x63,0x61,0x6E,0x20,0x49,0x20,0x74,0x6F,0x67,0x67,0x6C, - 0x65,0x20,0x66,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,0x6E, - 0x20,0x6D,0x6F,0x64,0x65,0x3F,0x37,0x3E,0x40,0x43,0x30,0x30, - 0x32,0x41,0x3A,0x20,0x50,0x72,0x65,0x73,0x73,0x20,0x41,0x6C, - 0x74,0x2B,0x45,0x6E,0x74,0x65,0x72,0x20,0x28,0x43,0x74,0x72, - 0x6C,0x2B,0x43,0x6D,0x64,0x2B,0x46,0x20,0x61,0x6C,0x73,0x6F, - 0x20,0x77,0x6F,0x72,0x6B,0x73,0x20,0x6F,0x6E,0x20,0x4D,0x61, - 0x63,0x29,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x45,0x3E,0x40, - 0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x48,0x6F,0x77,0x20,0x63, - 0x61,0x6E,0x20,0x49,0x20,0x6D,0x61,0x6B,0x65,0x20,0x66,0x75, - 0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20,0x6D,0x6F,0x64, - 0x65,0x20,0x73,0x74,0x72,0x65,0x74,0x63,0x68,0x20,0x6F,0x75, - 0x74,0x20,0x74,0x68,0x65,0x20,0x77,0x68,0x6F,0x6C,0x65,0x20, - 0x73,0x63,0x72,0x65,0x65,0x6E,0x3F,0x37,0x3E,0x40,0x43,0x30, - 0x30,0x32,0x41,0x3A,0x20,0x45,0x6E,0x61,0x62,0x6C,0x65,0x20, - 0x22,0x53,0x74,0x72,0x65,0x74,0x63,0x68,0x65,0x64,0x22,0x20, - 0x69,0x6E,0x20,0x43,0x6F,0x6E,0x66,0x69,0x67,0x20,0x2D,0x3E, - 0x20,0x4D,0x69,0x73,0x63,0x65,0x6C,0x6C,0x61,0x6E,0x65,0x6F, - 0x75,0x73,0x2E,0x4E,0x3E,0x40,0x58,0x30,0x33,0x35,0x54,0x68, - 0x69,0x73,0x20,0x77,0x69,0x6C,0x6C,0x20,0x72,0x65,0x73,0x75, - 0x6C,0x74,0x20,0x69,0x6E,0x20,0x75,0x6E,0x65,0x76,0x65,0x6E, - 0x20,0x70,0x69,0x78,0x65,0x6C,0x20,0x77,0x69,0x64,0x74,0x68, - 0x73,0x2E,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x77,0x61, - 0x6E,0x74,0x20,0x74,0x6F,0x20,0x66,0x69,0x78,0x20,0x74,0x68, - 0x69,0x73,0x2C,0x20,0x65,0x6E,0x61,0x62,0x6C,0x65,0x3D,0x22, - 0x50,0x69,0x78,0x65,0x6C,0x20,0x66,0x69,0x6C,0x74,0x65,0x72, - 0x22,0x20,0x28,0x74,0x68,0x6F,0x75,0x67,0x68,0x20,0x74,0x68, - 0x69,0x73,0x20,0x77,0x69,0x6C,0x6C,0x20,0x6D,0x61,0x6B,0x65, - 0x20,0x74,0x68,0x65,0x20,0x69,0x6D,0x61,0x67,0x65,0x20,0x6C, - 0x6F,0x6F,0x6B,0x20,0x62,0x6C,0x75,0x72,0x72,0x79,0x29,0x2E, - 0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x27,0x3E,0x40,0x43,0x30, - 0x30,0x31,0x51,0x3A,0x20,0x49,0x20,0x63,0x61,0x6E,0x27,0x74, - 0x20,0x75,0x73,0x65,0x20,0x41,0x6C,0x74,0x2B,0x46,0x34,0x20, - 0x61,0x6E,0x64,0x20,0x41,0x6C,0x74,0x2B,0x46,0x35,0x21,0x4E, - 0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x57,0x69,0x6E, - 0x64,0x6F,0x77,0x73,0x3A,0x20,0x49,0x66,0x20,0x79,0x6F,0x75, - 0x20,0x68,0x61,0x76,0x65,0x20,0x47,0x65,0x46,0x6F,0x72,0x63, - 0x65,0x20,0x45,0x78,0x70,0x65,0x72,0x69,0x65,0x6E,0x63,0x65, - 0x20,0x69,0x6E,0x73,0x74,0x61,0x6C,0x6C,0x65,0x64,0x2C,0x20, - 0x79,0x6F,0x75,0x20,0x6E,0x65,0x65,0x64,0x20,0x74,0x6F,0x20, - 0x63,0x68,0x61,0x6E,0x67,0x65,0x2B,0x3E,0x40,0x58,0x30,0x33, - 0x35,0x74,0x68,0x65,0x20,0x6B,0x65,0x79,0x62,0x69,0x6E,0x64, - 0x69,0x6E,0x67,0x73,0x20,0x69,0x6E,0x20,0x69,0x74,0x73,0x20, - 0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,0x70,0x61,0x67, - 0x65,0x2E,0x57,0x3E,0x6D,0x61,0x63,0x4F,0x53,0x2F,0x4F,0x53, - 0x20,0x58,0x3A,0x20,0x43,0x68,0x61,0x6E,0x67,0x65,0x20,0x41, - 0x6C,0x74,0x2B,0x46,0x34,0x2F,0x41,0x6C,0x74,0x2B,0x46,0x35, - 0x20,0x6B,0x65,0x79,0x73,0x20,0x69,0x6E,0x20,0x74,0x68,0x65, - 0x20,0x4F,0x53,0x20,0x74,0x6F,0x20,0x73,0x6F,0x6D,0x65,0x74, - 0x68,0x69,0x6E,0x67,0x20,0x65,0x6C,0x73,0x65,0x2E,0x20,0x41, - 0x6C,0x73,0x6F,0x20,0x66,0x6F,0x72,0x20,0x47,0x4E,0x55,0x2F, - 0x4C,0x69,0x6E,0x75,0x78,0x2E,0x06,0x3E,0x40,0x58,0x30,0x32, - 0x30,0x2B,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x54, - 0x68,0x65,0x20,0x6D,0x6F,0x75,0x73,0x65,0x20,0x63,0x75,0x72, - 0x73,0x6F,0x72,0x20,0x69,0x73,0x20,0x64,0x65,0x6C,0x61,0x79, - 0x65,0x64,0x2F,0x6C,0x61,0x67,0x67,0x79,0x21,0x44,0x3E,0x40, - 0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x4D,0x61,0x6B,0x65,0x20, - 0x73,0x75,0x72,0x65,0x20,0x22,0x53,0x6F,0x66,0x74,0x77,0x61, - 0x72,0x65,0x20,0x6D,0x6F,0x75,0x73,0x65,0x22,0x20,0x69,0x73, - 0x20,0x64,0x69,0x73,0x61,0x62,0x6C,0x65,0x64,0x20,0x69,0x6E, - 0x20,0x43,0x6F,0x6E,0x66,0x69,0x67,0x20,0x2D,0x3E,0x20,0x4C, - 0x61,0x79,0x6F,0x75,0x74,0x2E,0x4B,0x3E,0x40,0x58,0x30,0x33, - 0x35,0x41,0x6C,0x74,0x65,0x72,0x6E,0x61,0x74,0x69,0x76,0x65, - 0x6C,0x79,0x2C,0x20,0x79,0x6F,0x75,0x20,0x63,0x61,0x6E,0x20, - 0x65,0x6E,0x61,0x62,0x6C,0x65,0x20,0x22,0x56,0x53,0x79,0x6E, - 0x63,0x20,0x6F,0x66,0x66,0x22,0x20,0x69,0x6E,0x20,0x43,0x6F, - 0x6E,0x66,0x69,0x67,0x20,0x2D,0x3E,0x20,0x4D,0x69,0x73,0x63, - 0x65,0x6C,0x6C,0x61,0x6E,0x65,0x6F,0x75,0x73,0x2E,0x46,0x3E, - 0x54,0x68,0x69,0x73,0x20,0x68,0x6F,0x77,0x65,0x76,0x65,0x72, - 0x2C,0x20,0x77,0x69,0x6C,0x6C,0x20,0x69,0x6E,0x74,0x72,0x6F, - 0x64,0x75,0x63,0x65,0x20,0x73,0x74,0x75,0x74,0x74,0x65,0x72, - 0x69,0x6E,0x67,0x20,0x62,0x65,0x63,0x61,0x75,0x73,0x65,0x20, - 0x74,0x68,0x65,0x20,0x72,0x65,0x6E,0x64,0x65,0x72,0x69,0x6E, - 0x67,0x20,0x72,0x61,0x74,0x65,0x20,0x69,0x73,0x22,0x3E,0x6E, - 0x6F,0x74,0x20,0x65,0x78,0x61,0x63,0x74,0x20,0x74,0x6F,0x20, - 0x79,0x6F,0x75,0x72,0x20,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72, - 0x27,0x73,0x20,0x72,0x61,0x74,0x65,0x2E,0x06,0x3E,0x40,0x58, - 0x30,0x32,0x30,0x33,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A, - 0x20,0x57,0x69,0x6C,0x6C,0x20,0x79,0x6F,0x75,0x20,0x69,0x6D, - 0x70,0x6C,0x65,0x6D,0x65,0x6E,0x74,0x20,0x4D,0x49,0x44,0x49, - 0x20,0x6F,0x75,0x74,0x20,0x66,0x75,0x6E,0x63,0x74,0x69,0x6F, - 0x6E,0x61,0x6C,0x69,0x74,0x79,0x3F,0x4D,0x3E,0x40,0x43,0x30, - 0x30,0x32,0x41,0x3A,0x20,0x4E,0x6F,0x2C,0x20,0x73,0x6F,0x72, - 0x72,0x79,0x2E,0x20,0x54,0x68,0x69,0x73,0x20,0x69,0x73,0x20, - 0x76,0x65,0x72,0x79,0x20,0x64,0x69,0x66,0x66,0x69,0x63,0x75, - 0x6C,0x74,0x20,0x74,0x6F,0x20,0x69,0x6D,0x70,0x6C,0x65,0x6D, - 0x65,0x6E,0x74,0x20,0x63,0x6F,0x72,0x72,0x65,0x63,0x74,0x6C, - 0x79,0x20,0x77,0x68,0x65,0x6E,0x20,0x68,0x61,0x76,0x69,0x6E, - 0x67,0x3C,0x3E,0x40,0x58,0x30,0x33,0x35,0x68,0x69,0x67,0x68, - 0x65,0x72,0x20,0x61,0x75,0x64,0x69,0x6F,0x20,0x62,0x75,0x66, - 0x66,0x65,0x72,0x20,0x73,0x69,0x7A,0x65,0x73,0x20,0x28,0x62, - 0x75,0x66,0x66,0x65,0x72,0x65,0x64,0x20,0x72,0x65,0x70,0x6C, - 0x61,0x79,0x65,0x72,0x20,0x74,0x69,0x63,0x6B,0x73,0x29,0x2E, - 0x2E,0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x30,0x3E,0x40, - 0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x57,0x68,0x65,0x72,0x65, - 0x20,0x69,0x73,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x6E,0x66, - 0x69,0x67,0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x20,0x66,0x69, - 0x6C,0x65,0x20,0x73,0x74,0x6F,0x72,0x65,0x64,0x3F,0x3F,0x3E, + 0x73,0x20,0x69,0x6E,0x74,0x6F,0x20,0x74,0x68,0x65,0x20,0x63, + 0x6F,0x70,0x79,0x62,0x75,0x66,0x66,0x65,0x72,0x2E,0x3E,0x3E, + 0x50,0x20,0x6D,0x65,0x61,0x6E,0x73,0x20,0x70,0x61,0x73,0x74, + 0x65,0x20,0x61,0x6E,0x64,0x20,0x63,0x6F,0x6E,0x74,0x72,0x6F, + 0x6C,0x73,0x20,0x77,0x68,0x69,0x63,0x68,0x20,0x70,0x61,0x72, + 0x74,0x73,0x20,0x74,0x68,0x61,0x74,0x20,0x67,0x6F,0x65,0x73, + 0x20,0x6F,0x75,0x74,0x20,0x66,0x72,0x6F,0x6D,0x20,0x74,0x68, + 0x65,0x0B,0x63,0x6F,0x70,0x79,0x62,0x75,0x66,0x66,0x65,0x72, + 0x2E,0x45,0x3E,0x54,0x20,0x6D,0x65,0x61,0x6E,0x73,0x20,0x74, + 0x72,0x61,0x6E,0x73,0x70,0x61,0x72,0x65,0x6E,0x63,0x79,0x2E, + 0x20,0x49,0x66,0x20,0x69,0x74,0x27,0x73,0x20,0x65,0x6E,0x61, + 0x62,0x6C,0x65,0x64,0x2C,0x20,0x74,0x68,0x65,0x20,0x70,0x61, + 0x73,0x74,0x69,0x6E,0x67,0x20,0x64,0x6F,0x65,0x73,0x6E,0x27, + 0x74,0x20,0x6F,0x76,0x65,0x72,0x77,0x72,0x69,0x74,0x65,0x3D, + 0x64,0x61,0x74,0x61,0x20,0x77,0x69,0x74,0x68,0x20,0x6E,0x69, + 0x6C,0x2D,0x69,0x6E,0x66,0x6F,0x72,0x6D,0x61,0x74,0x69,0x6F, + 0x6E,0x2C,0x20,0x6F,0x6E,0x6C,0x79,0x20,0x77,0x69,0x74,0x68, + 0x20,0x61,0x20,0x6E,0x6F,0x74,0x65,0x20,0x6F,0x72,0x20,0x61, + 0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x20,0x3C,0x3E,0x20,0x30, + 0x2E,0x01,0x3E,0x40,0x3E,0x54,0x68,0x65,0x20,0x63,0x75,0x74, + 0x20,0x66,0x75,0x6E,0x63,0x74,0x69,0x6F,0x6E,0x73,0x20,0x77, + 0x6F,0x72,0x6B,0x73,0x20,0x6C,0x69,0x6B,0x65,0x20,0x70,0x61, + 0x73,0x74,0x69,0x6E,0x67,0x20,0x77,0x69,0x74,0x68,0x20,0x7A, + 0x65,0x72,0x6F,0x2D,0x64,0x61,0x74,0x61,0x2E,0x20,0x54,0x68, + 0x69,0x73,0x20,0x6D,0x65,0x61,0x6E,0x73,0x3B,0x74,0x68,0x61, + 0x74,0x20,0x74,0x68,0x65,0x20,0x63,0x75,0x74,0x74,0x69,0x6E, + 0x67,0x20,0x69,0x73,0x20,0x63,0x6F,0x6E,0x74,0x72,0x6F,0x6C, + 0x6C,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x50,0x2D,0x63, + 0x6F,0x6C,0x75,0x6D,0x6E,0x20,0x28,0x6F,0x72,0x20,0x54,0x2D, + 0x63,0x6F,0x6C,0x75,0x6D,0x6E,0x29,0x2E,0x3C,0x3E,0x57,0x68, + 0x65,0x6E,0x20,0x79,0x6F,0x75,0x20,0x63,0x6F,0x70,0x79,0x20, + 0x64,0x61,0x74,0x61,0x20,0x77,0x69,0x74,0x68,0x20,0x6D,0x61, + 0x73,0x6B,0x69,0x6E,0x67,0x2C,0x20,0x74,0x68,0x65,0x20,0x64, + 0x69,0x73,0x61,0x62,0x6C,0x65,0x64,0x20,0x70,0x61,0x72,0x74, + 0x73,0x20,0x61,0x72,0x65,0x20,0x6E,0x6F,0x74,0x43,0x63,0x6C, + 0x65,0x61,0x72,0x65,0x64,0x20,0x69,0x6E,0x20,0x74,0x68,0x65, + 0x20,0x63,0x6F,0x70,0x79,0x62,0x75,0x66,0x66,0x65,0x72,0x2E, + 0x20,0x28,0x4D,0x61,0x6B,0x69,0x6E,0x67,0x20,0x69,0x74,0x20, + 0x70,0x6F,0x73,0x73,0x69,0x62,0x6C,0x65,0x20,0x74,0x6F,0x20, + 0x63,0x6F,0x6C,0x6C,0x65,0x63,0x74,0x20,0x64,0x61,0x74,0x61, + 0x20,0x66,0x72,0x6F,0x6D,0x27,0x73,0x65,0x76,0x65,0x72,0x61, + 0x6C,0x20,0x6C,0x6F,0x63,0x61,0x74,0x69,0x6F,0x6E,0x73,0x20, + 0x69,0x6E,0x74,0x6F,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x70, + 0x79,0x62,0x75,0x66,0x66,0x65,0x72,0x2E,0x29,0x00,0x03,0x45, + 0x4E,0x44,0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x4C,0x3B,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x0E,0x40,0x4C,0x50,0x72,0x6F,0x62,0x6C,0x65,0x6D,0x73,0x2F, + 0x46,0x41,0x51,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x2A,0x3E, + 0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x48,0x6F,0x77,0x20, + 0x63,0x61,0x6E,0x20,0x49,0x20,0x74,0x6F,0x67,0x67,0x6C,0x65, + 0x20,0x66,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20, + 0x6D,0x6F,0x64,0x65,0x3F,0x37,0x3E,0x40,0x43,0x30,0x30,0x32, + 0x41,0x3A,0x20,0x50,0x72,0x65,0x73,0x73,0x20,0x41,0x6C,0x74, + 0x2B,0x45,0x6E,0x74,0x65,0x72,0x20,0x28,0x43,0x74,0x72,0x6C, + 0x2B,0x43,0x6D,0x64,0x2B,0x46,0x20,0x61,0x6C,0x73,0x6F,0x20, + 0x77,0x6F,0x72,0x6B,0x73,0x20,0x6F,0x6E,0x20,0x4D,0x61,0x63, + 0x29,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x45,0x3E,0x40,0x43, + 0x30,0x30,0x31,0x51,0x3A,0x20,0x48,0x6F,0x77,0x20,0x63,0x61, + 0x6E,0x20,0x49,0x20,0x6D,0x61,0x6B,0x65,0x20,0x66,0x75,0x6C, + 0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20,0x6D,0x6F,0x64,0x65, + 0x20,0x73,0x74,0x72,0x65,0x74,0x63,0x68,0x20,0x6F,0x75,0x74, + 0x20,0x74,0x68,0x65,0x20,0x77,0x68,0x6F,0x6C,0x65,0x20,0x73, + 0x63,0x72,0x65,0x65,0x6E,0x3F,0x37,0x3E,0x40,0x43,0x30,0x30, + 0x32,0x41,0x3A,0x20,0x45,0x6E,0x61,0x62,0x6C,0x65,0x20,0x22, + 0x53,0x74,0x72,0x65,0x74,0x63,0x68,0x65,0x64,0x22,0x20,0x69, + 0x6E,0x20,0x43,0x6F,0x6E,0x66,0x69,0x67,0x20,0x2D,0x3E,0x20, + 0x4D,0x69,0x73,0x63,0x65,0x6C,0x6C,0x61,0x6E,0x65,0x6F,0x75, + 0x73,0x2E,0x4E,0x3E,0x40,0x58,0x30,0x33,0x35,0x54,0x68,0x69, + 0x73,0x20,0x77,0x69,0x6C,0x6C,0x20,0x72,0x65,0x73,0x75,0x6C, + 0x74,0x20,0x69,0x6E,0x20,0x75,0x6E,0x65,0x76,0x65,0x6E,0x20, + 0x70,0x69,0x78,0x65,0x6C,0x20,0x77,0x69,0x64,0x74,0x68,0x73, + 0x2E,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x77,0x61,0x6E, + 0x74,0x20,0x74,0x6F,0x20,0x66,0x69,0x78,0x20,0x74,0x68,0x69, + 0x73,0x2C,0x20,0x65,0x6E,0x61,0x62,0x6C,0x65,0x3D,0x22,0x50, + 0x69,0x78,0x65,0x6C,0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x22, + 0x20,0x28,0x74,0x68,0x6F,0x75,0x67,0x68,0x20,0x74,0x68,0x69, + 0x73,0x20,0x77,0x69,0x6C,0x6C,0x20,0x6D,0x61,0x6B,0x65,0x20, + 0x74,0x68,0x65,0x20,0x69,0x6D,0x61,0x67,0x65,0x20,0x6C,0x6F, + 0x6F,0x6B,0x20,0x62,0x6C,0x75,0x72,0x72,0x79,0x29,0x2E,0x06, + 0x3E,0x40,0x58,0x30,0x32,0x30,0x27,0x3E,0x40,0x43,0x30,0x30, + 0x31,0x51,0x3A,0x20,0x49,0x20,0x63,0x61,0x6E,0x27,0x74,0x20, + 0x75,0x73,0x65,0x20,0x41,0x6C,0x74,0x2B,0x46,0x34,0x20,0x61, + 0x6E,0x64,0x20,0x41,0x6C,0x74,0x2B,0x46,0x35,0x21,0x4E,0x3E, 0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x57,0x69,0x6E,0x64, - 0x6F,0x77,0x73,0x3A,0x20,0x5C,0x55,0x73,0x65,0x72,0x73,0x5C, - 0x55,0x53,0x45,0x52,0x5C,0x41,0x70,0x70,0x44,0x61,0x74,0x61, - 0x5C,0x52,0x6F,0x61,0x6D,0x69,0x6E,0x67,0x5C,0x46,0x54,0x32, - 0x20,0x63,0x6C,0x6F,0x6E,0x65,0x5C,0x46,0x54,0x32,0x2E,0x43, - 0x46,0x47,0x45,0x3E,0x40,0x58,0x30,0x33,0x35,0x4F,0x53,0x20, - 0x58,0x3A,0x20,0x2F,0x55,0x73,0x65,0x72,0x73,0x2F,0x55,0x53, - 0x45,0x52,0x2F,0x4C,0x69,0x62,0x72,0x61,0x72,0x79,0x2F,0x41, - 0x70,0x70,0x6C,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53, - 0x75,0x70,0x70,0x6F,0x72,0x74,0x2F,0x46,0x54,0x32,0x20,0x63, - 0x6C,0x6F,0x6E,0x65,0x2F,0x46,0x54,0x32,0x2E,0x43,0x46,0x47, - 0x2F,0x47,0x4E,0x55,0x2F,0x4C,0x69,0x6E,0x75,0x78,0x3A,0x20, - 0x2F,0x68,0x6F,0x6D,0x65,0x2F,0x55,0x53,0x45,0x52,0x2F,0x2E, - 0x63,0x6F,0x6E,0x66,0x69,0x67,0x2F,0x46,0x54,0x32,0x20,0x63, - 0x6C,0x6F,0x6E,0x65,0x2F,0x46,0x54,0x32,0x2E,0x43,0x46,0x47, - 0x01,0x3E,0x48,0x49,0x74,0x20,0x77,0x69,0x6C,0x6C,0x20,0x62, - 0x65,0x20,0x73,0x74,0x6F,0x72,0x65,0x64,0x20,0x69,0x6E,0x20, - 0x74,0x68,0x65,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x20, - 0x64,0x69,0x72,0x65,0x63,0x74,0x6F,0x72,0x79,0x20,0x69,0x66, - 0x20,0x74,0x68,0x65,0x20,0x70,0x61,0x74,0x68,0x20,0x63,0x6F, - 0x75,0x6C,0x64,0x6E,0x27,0x74,0x20,0x62,0x65,0x20,0x75,0x73, - 0x65,0x64,0x2E,0x4D,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x70, - 0x75,0x74,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x6E,0x66,0x69, + 0x6F,0x77,0x73,0x3A,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x20, + 0x68,0x61,0x76,0x65,0x20,0x47,0x65,0x46,0x6F,0x72,0x63,0x65, + 0x20,0x45,0x78,0x70,0x65,0x72,0x69,0x65,0x6E,0x63,0x65,0x20, + 0x69,0x6E,0x73,0x74,0x61,0x6C,0x6C,0x65,0x64,0x2C,0x20,0x79, + 0x6F,0x75,0x20,0x6E,0x65,0x65,0x64,0x20,0x74,0x6F,0x20,0x63, + 0x68,0x61,0x6E,0x67,0x65,0x2B,0x3E,0x40,0x58,0x30,0x33,0x35, + 0x74,0x68,0x65,0x20,0x6B,0x65,0x79,0x62,0x69,0x6E,0x64,0x69, + 0x6E,0x67,0x73,0x20,0x69,0x6E,0x20,0x69,0x74,0x73,0x20,0x73, + 0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,0x70,0x61,0x67,0x65, + 0x2E,0x57,0x3E,0x6D,0x61,0x63,0x4F,0x53,0x2F,0x4F,0x53,0x20, + 0x58,0x3A,0x20,0x43,0x68,0x61,0x6E,0x67,0x65,0x20,0x41,0x6C, + 0x74,0x2B,0x46,0x34,0x2F,0x41,0x6C,0x74,0x2B,0x46,0x35,0x20, + 0x6B,0x65,0x79,0x73,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20, + 0x4F,0x53,0x20,0x74,0x6F,0x20,0x73,0x6F,0x6D,0x65,0x74,0x68, + 0x69,0x6E,0x67,0x20,0x65,0x6C,0x73,0x65,0x2E,0x20,0x41,0x6C, + 0x73,0x6F,0x20,0x66,0x6F,0x72,0x20,0x47,0x4E,0x55,0x2F,0x4C, + 0x69,0x6E,0x75,0x78,0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,0x30, + 0x2B,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x54,0x68, + 0x65,0x20,0x6D,0x6F,0x75,0x73,0x65,0x20,0x63,0x75,0x72,0x73, + 0x6F,0x72,0x20,0x69,0x73,0x20,0x64,0x65,0x6C,0x61,0x79,0x65, + 0x64,0x2F,0x6C,0x61,0x67,0x67,0x79,0x21,0x44,0x3E,0x40,0x43, + 0x30,0x30,0x32,0x41,0x3A,0x20,0x4D,0x61,0x6B,0x65,0x20,0x73, + 0x75,0x72,0x65,0x20,0x22,0x53,0x6F,0x66,0x74,0x77,0x61,0x72, + 0x65,0x20,0x6D,0x6F,0x75,0x73,0x65,0x22,0x20,0x69,0x73,0x20, + 0x64,0x69,0x73,0x61,0x62,0x6C,0x65,0x64,0x20,0x69,0x6E,0x20, + 0x43,0x6F,0x6E,0x66,0x69,0x67,0x20,0x2D,0x3E,0x20,0x4C,0x61, + 0x79,0x6F,0x75,0x74,0x2E,0x4B,0x3E,0x40,0x58,0x30,0x33,0x35, + 0x41,0x6C,0x74,0x65,0x72,0x6E,0x61,0x74,0x69,0x76,0x65,0x6C, + 0x79,0x2C,0x20,0x79,0x6F,0x75,0x20,0x63,0x61,0x6E,0x20,0x65, + 0x6E,0x61,0x62,0x6C,0x65,0x20,0x22,0x56,0x53,0x79,0x6E,0x63, + 0x20,0x6F,0x66,0x66,0x22,0x20,0x69,0x6E,0x20,0x43,0x6F,0x6E, + 0x66,0x69,0x67,0x20,0x2D,0x3E,0x20,0x4D,0x69,0x73,0x63,0x65, + 0x6C,0x6C,0x61,0x6E,0x65,0x6F,0x75,0x73,0x2E,0x46,0x3E,0x54, + 0x68,0x69,0x73,0x20,0x68,0x6F,0x77,0x65,0x76,0x65,0x72,0x2C, + 0x20,0x77,0x69,0x6C,0x6C,0x20,0x69,0x6E,0x74,0x72,0x6F,0x64, + 0x75,0x63,0x65,0x20,0x73,0x74,0x75,0x74,0x74,0x65,0x72,0x69, + 0x6E,0x67,0x20,0x62,0x65,0x63,0x61,0x75,0x73,0x65,0x20,0x74, + 0x68,0x65,0x20,0x72,0x65,0x6E,0x64,0x65,0x72,0x69,0x6E,0x67, + 0x20,0x72,0x61,0x74,0x65,0x20,0x69,0x73,0x22,0x3E,0x6E,0x6F, + 0x74,0x20,0x65,0x78,0x61,0x63,0x74,0x20,0x74,0x6F,0x20,0x79, + 0x6F,0x75,0x72,0x20,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x27, + 0x73,0x20,0x72,0x61,0x74,0x65,0x2E,0x06,0x3E,0x40,0x58,0x30, + 0x32,0x30,0x33,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20, + 0x57,0x69,0x6C,0x6C,0x20,0x79,0x6F,0x75,0x20,0x69,0x6D,0x70, + 0x6C,0x65,0x6D,0x65,0x6E,0x74,0x20,0x4D,0x49,0x44,0x49,0x20, + 0x6F,0x75,0x74,0x20,0x66,0x75,0x6E,0x63,0x74,0x69,0x6F,0x6E, + 0x61,0x6C,0x69,0x74,0x79,0x3F,0x4D,0x3E,0x40,0x43,0x30,0x30, + 0x32,0x41,0x3A,0x20,0x4E,0x6F,0x2C,0x20,0x73,0x6F,0x72,0x72, + 0x79,0x2E,0x20,0x54,0x68,0x69,0x73,0x20,0x69,0x73,0x20,0x76, + 0x65,0x72,0x79,0x20,0x64,0x69,0x66,0x66,0x69,0x63,0x75,0x6C, + 0x74,0x20,0x74,0x6F,0x20,0x69,0x6D,0x70,0x6C,0x65,0x6D,0x65, + 0x6E,0x74,0x20,0x63,0x6F,0x72,0x72,0x65,0x63,0x74,0x6C,0x79, + 0x20,0x77,0x68,0x65,0x6E,0x20,0x68,0x61,0x76,0x69,0x6E,0x67, + 0x3C,0x3E,0x40,0x58,0x30,0x33,0x35,0x68,0x69,0x67,0x68,0x65, + 0x72,0x20,0x61,0x75,0x64,0x69,0x6F,0x20,0x62,0x75,0x66,0x66, + 0x65,0x72,0x20,0x73,0x69,0x7A,0x65,0x73,0x20,0x28,0x62,0x75, + 0x66,0x66,0x65,0x72,0x65,0x64,0x20,0x72,0x65,0x70,0x6C,0x61, + 0x79,0x65,0x72,0x20,0x74,0x69,0x63,0x6B,0x73,0x29,0x2E,0x2E, + 0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x30,0x3E,0x40,0x43, + 0x30,0x30,0x31,0x51,0x3A,0x20,0x57,0x68,0x65,0x72,0x65,0x20, + 0x69,0x73,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x6E,0x66,0x69, 0x67,0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x20,0x66,0x69,0x6C, - 0x65,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x70,0x72,0x6F, - 0x67,0x72,0x61,0x6D,0x20,0x64,0x69,0x72,0x65,0x63,0x74,0x6F, - 0x72,0x79,0x2C,0x20,0x69,0x74,0x20,0x77,0x69,0x6C,0x6C,0x20, - 0x72,0x65,0x61,0x64,0x20,0x74,0x68,0x61,0x74,0x4A,0x6F,0x6E, - 0x65,0x20,0x61,0x6E,0x64,0x20,0x6E,0x6F,0x74,0x20,0x61,0x74, - 0x74,0x65,0x6D,0x70,0x74,0x20,0x74,0x6F,0x20,0x63,0x72,0x65, - 0x61,0x74,0x65,0x20,0x63,0x6F,0x6E,0x66,0x69,0x67,0x20,0x64, - 0x69,0x72,0x73,0x20,0x66,0x6F,0x72,0x20,0x74,0x68,0x65,0x20, - 0x4F,0x53,0x20,0x75,0x73,0x65,0x72,0x2E,0x20,0x28,0x70,0x6F, - 0x72,0x74,0x61,0x62,0x6C,0x65,0x20,0x6D,0x6F,0x64,0x65,0x29, - 0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x42,0x3E,0x40,0x43,0x30, - 0x30,0x31,0x51,0x3A,0x20,0x43,0x61,0x6E,0x20,0x74,0x68,0x65, - 0x20,0x63,0x6C,0x6F,0x6E,0x65,0x20,0x72,0x65,0x61,0x64,0x20, - 0x46,0x54,0x32,0x2E,0x43,0x46,0x47,0x20,0x66,0x72,0x6F,0x6D, - 0x20,0x72,0x65,0x61,0x6C,0x20,0x46,0x54,0x32,0x2C,0x20,0x61, - 0x6E,0x64,0x20,0x76,0x69,0x63,0x65,0x20,0x76,0x65,0x72,0x73, - 0x61,0x3F,0x4C,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20, - 0x59,0x65,0x73,0x2C,0x20,0x69,0x74,0x20,0x73,0x68,0x6F,0x75, - 0x6C,0x64,0x20,0x77,0x6F,0x72,0x6B,0x20,0x6A,0x75,0x73,0x74, - 0x20,0x66,0x69,0x6E,0x65,0x2E,0x20,0x50,0x75,0x74,0x20,0x69, - 0x74,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x64,0x69,0x72, - 0x65,0x63,0x74,0x6F,0x72,0x79,0x20,0x73,0x68,0x6F,0x77,0x6E, - 0x20,0x61,0x62,0x6F,0x76,0x65,0x2E,0x06,0x3E,0x40,0x58,0x30, - 0x32,0x30,0x51,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20, - 0x53,0x6D,0x70,0x2E,0x20,0x45,0x64,0x2E,0x3A,0x20,0x57,0x68, - 0x69,0x6C,0x65,0x20,0x7A,0x6F,0x6F,0x6D,0x65,0x64,0x20,0x69, - 0x6E,0x2C,0x20,0x49,0x20,0x73,0x6F,0x6D,0x65,0x74,0x69,0x6D, - 0x65,0x73,0x20,0x63,0x61,0x6E,0x27,0x74,0x20,0x6D,0x61,0x72, - 0x6B,0x20,0x74,0x68,0x65,0x20,0x6C,0x61,0x73,0x74,0x20,0x73, - 0x61,0x6D,0x70,0x6C,0x65,0x20,0x70,0x6F,0x69,0x6E,0x74,0x21, - 0x47,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x54,0x68, - 0x69,0x73,0x20,0x69,0x73,0x20,0x6E,0x6F,0x72,0x6D,0x61,0x6C, - 0x2E,0x20,0x54,0x68,0x69,0x73,0x20,0x69,0x73,0x20,0x61,0x20, - 0x6C,0x69,0x6D,0x69,0x74,0x61,0x74,0x69,0x6F,0x6E,0x20,0x69, - 0x6E,0x20,0x74,0x68,0x65,0x20,0x6E,0x61,0x74,0x75,0x72,0x65, - 0x20,0x6F,0x66,0x20,0x73,0x63,0x61,0x6C,0x69,0x6E,0x67,0x2E, - 0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x17,0x3E,0x40,0x43,0x30, - 0x30,0x31,0x51,0x3A,0x20,0x49,0x20,0x66,0x6F,0x75,0x6E,0x64, - 0x20,0x61,0x20,0x62,0x75,0x67,0x21,0x4C,0x3E,0x40,0x43,0x30, - 0x30,0x32,0x41,0x3A,0x20,0x50,0x6C,0x65,0x61,0x73,0x65,0x20, - 0x73,0x65,0x6E,0x64,0x20,0x6D,0x65,0x20,0x61,0x20,0x6D,0x61, - 0x69,0x6C,0x20,0x28,0x66,0x6F,0x75,0x6E,0x64,0x20,0x61,0x74, - 0x20,0x31,0x36,0x2D,0x62,0x69,0x74,0x73,0x2E,0x6F,0x72,0x67, - 0x29,0x20,0x61,0x6E,0x64,0x20,0x74,0x72,0x79,0x20,0x74,0x6F, - 0x20,0x65,0x78,0x70,0x6C,0x61,0x69,0x6E,0x20,0x69,0x74,0x2E, - 0x00,0x03,0x45,0x4E,0x44,0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x4C,0x3B, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, - 0x2A,0x2A,0x2A,0x0C,0x40,0x4C,0x4B,0x6E,0x6F,0x77,0x6E,0x20, - 0x62,0x75,0x67,0x73,0x01,0x3E,0x31,0x3E,0x40,0x58,0x30,0x31, - 0x30,0x40,0x43,0x30,0x30,0x31,0x57,0x41,0x56,0x20,0x65,0x78, - 0x70,0x6F,0x72,0x74,0x69,0x6E,0x67,0x20,0x28,0x72,0x65,0x6E, - 0x64,0x65,0x72,0x69,0x6E,0x67,0x20,0x73,0x6F,0x6E,0x67,0x20, - 0x74,0x6F,0x20,0x57,0x41,0x56,0x29,0x3A,0x01,0x3E,0x55,0x3E, - 0x40,0x58,0x30,0x31,0x30,0x40,0x43,0x30,0x30,0x32,0x2D,0x20, - 0x53,0x6F,0x6E,0x67,0x73,0x20,0x74,0x68,0x61,0x74,0x20,0x6A, - 0x75,0x6D,0x70,0x20,0x62,0x61,0x63,0x6B,0x20,0x74,0x6F,0x20, - 0x61,0x20,0x70,0x72,0x65,0x76,0x69,0x6F,0x75,0x73,0x20,0x70, - 0x61,0x74,0x74,0x65,0x72,0x6E,0x20,0x77,0x69,0x6C,0x6C,0x20, - 0x72,0x65,0x6E,0x64,0x65,0x72,0x20,0x66,0x6F,0x72,0x65,0x76, - 0x65,0x72,0x20,0x61,0x6E,0x64,0x20,0x65,0x76,0x65,0x72,0x2C, - 0x4D,0x3E,0x40,0x58,0x30,0x32,0x31,0x61,0x6E,0x64,0x20,0x79, - 0x6F,0x75,0x20,0x6E,0x65,0x65,0x64,0x20,0x74,0x6F,0x20,0x70, - 0x72,0x65,0x73,0x73,0x20,0x61,0x20,0x6B,0x65,0x79,0x20,0x6F, - 0x72,0x20,0x63,0x6C,0x69,0x63,0x6B,0x20,0x74,0x68,0x65,0x20, - 0x6D,0x6F,0x75,0x73,0x65,0x20,0x74,0x6F,0x20,0x61,0x62,0x6F, - 0x72,0x74,0x20,0x74,0x68,0x65,0x20,0x72,0x65,0x6E,0x64,0x65, - 0x72,0x20,0x77,0x68,0x65,0x6E,0x15,0x3E,0x40,0x58,0x30,0x32, - 0x31,0x79,0x6F,0x75,0x20,0x77,0x61,0x6E,0x74,0x20,0x69,0x74, - 0x20,0x74,0x6F,0x2E,0x01,0x3E,0x11,0x3E,0x40,0x58,0x30,0x31, - 0x30,0x40,0x43,0x30,0x30,0x31,0x56,0x69,0x64,0x65,0x6F,0x3A, - 0x06,0x3E,0x40,0x43,0x30,0x30,0x32,0x50,0x3E,0x40,0x58,0x30, - 0x31,0x30,0x2D,0x20,0x46,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65, - 0x65,0x6E,0x20,0x6D,0x6F,0x64,0x65,0x20,0x63,0x61,0x6E,0x20, - 0x62,0x65,0x20,0x75,0x6E,0x62,0x65,0x61,0x72,0x61,0x62,0x6C, - 0x79,0x20,0x73,0x6C,0x6F,0x77,0x20,0x6F,0x6E,0x20,0x61,0x20, - 0x52,0x61,0x73,0x70,0x62,0x65,0x72,0x72,0x79,0x20,0x50,0x69, - 0x20,0x28,0x65,0x76,0x65,0x6E,0x20,0x6F,0x6E,0x20,0x52,0x50, - 0x69,0x20,0x34,0x29,0x4A,0x3E,0x40,0x58,0x30,0x31,0x30,0x2D, - 0x20,0x46,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20, - 0x6D,0x6F,0x64,0x65,0x20,0x63,0x61,0x6E,0x20,0x68,0x61,0x76, - 0x65,0x20,0x73,0x65,0x76,0x65,0x72,0x61,0x6C,0x20,0x70,0x72, - 0x6F,0x62,0x6C,0x65,0x6D,0x73,0x20,0x6F,0x6E,0x20,0x6D,0x75, - 0x6C,0x74,0x69,0x2D,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x20, - 0x73,0x79,0x73,0x74,0x65,0x6D,0x73,0x47,0x3E,0x40,0x58,0x30, - 0x31,0x30,0x2D,0x20,0x46,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65, - 0x65,0x6E,0x20,0x6D,0x6F,0x64,0x65,0x20,0x63,0x61,0x6E,0x20, - 0x68,0x61,0x76,0x65,0x20,0x73,0x65,0x76,0x65,0x72,0x61,0x6C, - 0x20,0x70,0x72,0x6F,0x62,0x6C,0x65,0x6D,0x73,0x20,0x6F,0x6E, - 0x20,0x73,0x6F,0x6D,0x65,0x20,0x4C,0x69,0x6E,0x75,0x78,0x20, - 0x73,0x79,0x73,0x74,0x65,0x6D,0x73,0x00,0x03,0x45,0x4E,0x44 + 0x65,0x20,0x73,0x74,0x6F,0x72,0x65,0x64,0x3F,0x3F,0x3E,0x40, + 0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x57,0x69,0x6E,0x64,0x6F, + 0x77,0x73,0x3A,0x20,0x5C,0x55,0x73,0x65,0x72,0x73,0x5C,0x55, + 0x53,0x45,0x52,0x5C,0x41,0x70,0x70,0x44,0x61,0x74,0x61,0x5C, + 0x52,0x6F,0x61,0x6D,0x69,0x6E,0x67,0x5C,0x46,0x54,0x32,0x20, + 0x63,0x6C,0x6F,0x6E,0x65,0x5C,0x46,0x54,0x32,0x2E,0x43,0x46, + 0x47,0x45,0x3E,0x40,0x58,0x30,0x33,0x35,0x4F,0x53,0x20,0x58, + 0x3A,0x20,0x2F,0x55,0x73,0x65,0x72,0x73,0x2F,0x55,0x53,0x45, + 0x52,0x2F,0x4C,0x69,0x62,0x72,0x61,0x72,0x79,0x2F,0x41,0x70, + 0x70,0x6C,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x75, + 0x70,0x70,0x6F,0x72,0x74,0x2F,0x46,0x54,0x32,0x20,0x63,0x6C, + 0x6F,0x6E,0x65,0x2F,0x46,0x54,0x32,0x2E,0x43,0x46,0x47,0x2F, + 0x47,0x4E,0x55,0x2F,0x4C,0x69,0x6E,0x75,0x78,0x3A,0x20,0x2F, + 0x68,0x6F,0x6D,0x65,0x2F,0x55,0x53,0x45,0x52,0x2F,0x2E,0x63, + 0x6F,0x6E,0x66,0x69,0x67,0x2F,0x46,0x54,0x32,0x20,0x63,0x6C, + 0x6F,0x6E,0x65,0x2F,0x46,0x54,0x32,0x2E,0x43,0x46,0x47,0x01, + 0x3E,0x48,0x49,0x74,0x20,0x77,0x69,0x6C,0x6C,0x20,0x62,0x65, + 0x20,0x73,0x74,0x6F,0x72,0x65,0x64,0x20,0x69,0x6E,0x20,0x74, + 0x68,0x65,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x20,0x64, + 0x69,0x72,0x65,0x63,0x74,0x6F,0x72,0x79,0x20,0x69,0x66,0x20, + 0x74,0x68,0x65,0x20,0x70,0x61,0x74,0x68,0x20,0x63,0x6F,0x75, + 0x6C,0x64,0x6E,0x27,0x74,0x20,0x62,0x65,0x20,0x75,0x73,0x65, + 0x64,0x2E,0x4D,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x70,0x75, + 0x74,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x6E,0x66,0x69,0x67, + 0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x20,0x66,0x69,0x6C,0x65, + 0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x70,0x72,0x6F,0x67, + 0x72,0x61,0x6D,0x20,0x64,0x69,0x72,0x65,0x63,0x74,0x6F,0x72, + 0x79,0x2C,0x20,0x69,0x74,0x20,0x77,0x69,0x6C,0x6C,0x20,0x72, + 0x65,0x61,0x64,0x20,0x74,0x68,0x61,0x74,0x4A,0x6F,0x6E,0x65, + 0x20,0x61,0x6E,0x64,0x20,0x6E,0x6F,0x74,0x20,0x61,0x74,0x74, + 0x65,0x6D,0x70,0x74,0x20,0x74,0x6F,0x20,0x63,0x72,0x65,0x61, + 0x74,0x65,0x20,0x63,0x6F,0x6E,0x66,0x69,0x67,0x20,0x64,0x69, + 0x72,0x73,0x20,0x66,0x6F,0x72,0x20,0x74,0x68,0x65,0x20,0x4F, + 0x53,0x20,0x75,0x73,0x65,0x72,0x2E,0x20,0x28,0x70,0x6F,0x72, + 0x74,0x61,0x62,0x6C,0x65,0x20,0x6D,0x6F,0x64,0x65,0x29,0x06, + 0x3E,0x40,0x58,0x30,0x32,0x30,0x42,0x3E,0x40,0x43,0x30,0x30, + 0x31,0x51,0x3A,0x20,0x43,0x61,0x6E,0x20,0x74,0x68,0x65,0x20, + 0x63,0x6C,0x6F,0x6E,0x65,0x20,0x72,0x65,0x61,0x64,0x20,0x46, + 0x54,0x32,0x2E,0x43,0x46,0x47,0x20,0x66,0x72,0x6F,0x6D,0x20, + 0x72,0x65,0x61,0x6C,0x20,0x46,0x54,0x32,0x2C,0x20,0x61,0x6E, + 0x64,0x20,0x76,0x69,0x63,0x65,0x20,0x76,0x65,0x72,0x73,0x61, + 0x3F,0x4C,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x59, + 0x65,0x73,0x2C,0x20,0x69,0x74,0x20,0x73,0x68,0x6F,0x75,0x6C, + 0x64,0x20,0x77,0x6F,0x72,0x6B,0x20,0x6A,0x75,0x73,0x74,0x20, + 0x66,0x69,0x6E,0x65,0x2E,0x20,0x50,0x75,0x74,0x20,0x69,0x74, + 0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x64,0x69,0x72,0x65, + 0x63,0x74,0x6F,0x72,0x79,0x20,0x73,0x68,0x6F,0x77,0x6E,0x20, + 0x61,0x62,0x6F,0x76,0x65,0x2E,0x06,0x3E,0x40,0x58,0x30,0x32, + 0x30,0x51,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x53, + 0x6D,0x70,0x2E,0x20,0x45,0x64,0x2E,0x3A,0x20,0x57,0x68,0x69, + 0x6C,0x65,0x20,0x7A,0x6F,0x6F,0x6D,0x65,0x64,0x20,0x69,0x6E, + 0x2C,0x20,0x49,0x20,0x73,0x6F,0x6D,0x65,0x74,0x69,0x6D,0x65, + 0x73,0x20,0x63,0x61,0x6E,0x27,0x74,0x20,0x6D,0x61,0x72,0x6B, + 0x20,0x74,0x68,0x65,0x20,0x6C,0x61,0x73,0x74,0x20,0x73,0x61, + 0x6D,0x70,0x6C,0x65,0x20,0x70,0x6F,0x69,0x6E,0x74,0x21,0x47, + 0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x54,0x68,0x69, + 0x73,0x20,0x69,0x73,0x20,0x6E,0x6F,0x72,0x6D,0x61,0x6C,0x2E, + 0x20,0x54,0x68,0x69,0x73,0x20,0x69,0x73,0x20,0x61,0x20,0x6C, + 0x69,0x6D,0x69,0x74,0x61,0x74,0x69,0x6F,0x6E,0x20,0x69,0x6E, + 0x20,0x74,0x68,0x65,0x20,0x6E,0x61,0x74,0x75,0x72,0x65,0x20, + 0x6F,0x66,0x20,0x73,0x63,0x61,0x6C,0x69,0x6E,0x67,0x2E,0x06, + 0x3E,0x40,0x58,0x30,0x32,0x30,0x17,0x3E,0x40,0x43,0x30,0x30, + 0x31,0x51,0x3A,0x20,0x49,0x20,0x66,0x6F,0x75,0x6E,0x64,0x20, + 0x61,0x20,0x62,0x75,0x67,0x21,0x4C,0x3E,0x40,0x43,0x30,0x30, + 0x32,0x41,0x3A,0x20,0x50,0x6C,0x65,0x61,0x73,0x65,0x20,0x73, + 0x65,0x6E,0x64,0x20,0x6D,0x65,0x20,0x61,0x20,0x6D,0x61,0x69, + 0x6C,0x20,0x28,0x66,0x6F,0x75,0x6E,0x64,0x20,0x61,0x74,0x20, + 0x31,0x36,0x2D,0x62,0x69,0x74,0x73,0x2E,0x6F,0x72,0x67,0x29, + 0x20,0x61,0x6E,0x64,0x20,0x74,0x72,0x79,0x20,0x74,0x6F,0x20, + 0x65,0x78,0x70,0x6C,0x61,0x69,0x6E,0x20,0x69,0x74,0x2E,0x00, + 0x03,0x45,0x4E,0x44,0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x4C,0x3B,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A, + 0x2A,0x2A,0x0C,0x40,0x4C,0x4B,0x6E,0x6F,0x77,0x6E,0x20,0x62, + 0x75,0x67,0x73,0x01,0x3E,0x31,0x3E,0x40,0x58,0x30,0x31,0x30, + 0x40,0x43,0x30,0x30,0x31,0x57,0x41,0x56,0x20,0x65,0x78,0x70, + 0x6F,0x72,0x74,0x69,0x6E,0x67,0x20,0x28,0x72,0x65,0x6E,0x64, + 0x65,0x72,0x69,0x6E,0x67,0x20,0x73,0x6F,0x6E,0x67,0x20,0x74, + 0x6F,0x20,0x57,0x41,0x56,0x29,0x3A,0x01,0x3E,0x55,0x3E,0x40, + 0x58,0x30,0x31,0x30,0x40,0x43,0x30,0x30,0x32,0x2D,0x20,0x53, + 0x6F,0x6E,0x67,0x73,0x20,0x74,0x68,0x61,0x74,0x20,0x6A,0x75, + 0x6D,0x70,0x20,0x62,0x61,0x63,0x6B,0x20,0x74,0x6F,0x20,0x61, + 0x20,0x70,0x72,0x65,0x76,0x69,0x6F,0x75,0x73,0x20,0x70,0x61, + 0x74,0x74,0x65,0x72,0x6E,0x20,0x77,0x69,0x6C,0x6C,0x20,0x72, + 0x65,0x6E,0x64,0x65,0x72,0x20,0x66,0x6F,0x72,0x65,0x76,0x65, + 0x72,0x20,0x61,0x6E,0x64,0x20,0x65,0x76,0x65,0x72,0x2C,0x4D, + 0x3E,0x40,0x58,0x30,0x32,0x31,0x61,0x6E,0x64,0x20,0x79,0x6F, + 0x75,0x20,0x6E,0x65,0x65,0x64,0x20,0x74,0x6F,0x20,0x70,0x72, + 0x65,0x73,0x73,0x20,0x61,0x20,0x6B,0x65,0x79,0x20,0x6F,0x72, + 0x20,0x63,0x6C,0x69,0x63,0x6B,0x20,0x74,0x68,0x65,0x20,0x6D, + 0x6F,0x75,0x73,0x65,0x20,0x74,0x6F,0x20,0x61,0x62,0x6F,0x72, + 0x74,0x20,0x74,0x68,0x65,0x20,0x72,0x65,0x6E,0x64,0x65,0x72, + 0x20,0x77,0x68,0x65,0x6E,0x15,0x3E,0x40,0x58,0x30,0x32,0x31, + 0x79,0x6F,0x75,0x20,0x77,0x61,0x6E,0x74,0x20,0x69,0x74,0x20, + 0x74,0x6F,0x2E,0x01,0x3E,0x11,0x3E,0x40,0x58,0x30,0x31,0x30, + 0x40,0x43,0x30,0x30,0x31,0x56,0x69,0x64,0x65,0x6F,0x3A,0x06, + 0x3E,0x40,0x43,0x30,0x30,0x32,0x50,0x3E,0x40,0x58,0x30,0x31, + 0x30,0x2D,0x20,0x46,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65, + 0x6E,0x20,0x6D,0x6F,0x64,0x65,0x20,0x63,0x61,0x6E,0x20,0x62, + 0x65,0x20,0x75,0x6E,0x62,0x65,0x61,0x72,0x61,0x62,0x6C,0x79, + 0x20,0x73,0x6C,0x6F,0x77,0x20,0x6F,0x6E,0x20,0x61,0x20,0x52, + 0x61,0x73,0x70,0x62,0x65,0x72,0x72,0x79,0x20,0x50,0x69,0x20, + 0x28,0x65,0x76,0x65,0x6E,0x20,0x6F,0x6E,0x20,0x52,0x50,0x69, + 0x20,0x34,0x29,0x4A,0x3E,0x40,0x58,0x30,0x31,0x30,0x2D,0x20, + 0x46,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20,0x6D, + 0x6F,0x64,0x65,0x20,0x63,0x61,0x6E,0x20,0x68,0x61,0x76,0x65, + 0x20,0x73,0x65,0x76,0x65,0x72,0x61,0x6C,0x20,0x70,0x72,0x6F, + 0x62,0x6C,0x65,0x6D,0x73,0x20,0x6F,0x6E,0x20,0x6D,0x75,0x6C, + 0x74,0x69,0x2D,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x20,0x73, + 0x79,0x73,0x74,0x65,0x6D,0x73,0x47,0x3E,0x40,0x58,0x30,0x31, + 0x30,0x2D,0x20,0x46,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65, + 0x6E,0x20,0x6D,0x6F,0x64,0x65,0x20,0x63,0x61,0x6E,0x20,0x68, + 0x61,0x76,0x65,0x20,0x73,0x65,0x76,0x65,0x72,0x61,0x6C,0x20, + 0x70,0x72,0x6F,0x62,0x6C,0x65,0x6D,0x73,0x20,0x6F,0x6E,0x20, + 0x73,0x6F,0x6D,0x65,0x20,0x4C,0x69,0x6E,0x75,0x78,0x20,0x73, + 0x79,0x73,0x74,0x65,0x6D,0x73,0x00,0x03,0x45,0x4E,0x44 }; #endif diff --git a/src/mixer/ft2_center_mix.c b/src/mixer/ft2_center_mix.c @@ -625,6 +625,185 @@ void centerMix8bBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSam SET_BACK_MIXER_POS } +void centerMix8bNoLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int8_t *base, *smpPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac; + + GET_VOL_MONO + GET_MIXER_VARS + SET_BASE8 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + samplesLeft -= samplesToMix; + + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_MONO_CINTRP + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_MONO_CINTRP + INC_POS + RENDER_8BIT_SMP_MONO_CINTRP + INC_POS + RENDER_8BIT_SMP_MONO_CINTRP + INC_POS + RENDER_8BIT_SMP_MONO_CINTRP + INC_POS + } + + HANDLE_SAMPLE_END + } + + SET_BACK_MIXER_POS +} + +void centerMix8bLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int8_t *base, *smpPtr; + int8_t *smpTapPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac; + + GET_VOL_MONO + GET_MIXER_VARS + SET_BASE8 + PREPARE_TAP_FIX8 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + samplesLeft -= samplesToMix; + + if (v->hasLooped) // the negative interpolation taps need a special case after the sample has looped once + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + INC_POS + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + INC_POS + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + INC_POS + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + INC_POS + } + } + else + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_MONO_CINTRP + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_MONO_CINTRP + INC_POS + RENDER_8BIT_SMP_MONO_CINTRP + INC_POS + RENDER_8BIT_SMP_MONO_CINTRP + INC_POS + RENDER_8BIT_SMP_MONO_CINTRP + INC_POS + } + } + + WRAP_LOOP + } + + SET_BACK_MIXER_POS +} + +void centerMix8bBidiLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int8_t *base, *revBase, *smpPtr; + int8_t *smpTapPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac, tmpDelta; + + GET_VOL_MONO + GET_MIXER_VARS + SET_BASE8_BIDI + PREPARE_TAP_FIX8 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + samplesLeft -= samplesToMix; + + START_BIDI + if (v->hasLooped) // the negative interpolation taps need a special case after the sample has looped once + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + INC_POS_BIDI + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + INC_POS_BIDI + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + INC_POS_BIDI + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + INC_POS_BIDI + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + INC_POS_BIDI + } + } + else + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_MONO_CINTRP + INC_POS_BIDI + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_MONO_CINTRP + INC_POS_BIDI + RENDER_8BIT_SMP_MONO_CINTRP + INC_POS_BIDI + RENDER_8BIT_SMP_MONO_CINTRP + INC_POS_BIDI + RENDER_8BIT_SMP_MONO_CINTRP + INC_POS_BIDI + } + } + + END_BIDI + + WRAP_BIDI_LOOP + } + + SET_BACK_MIXER_POS +} + void centerMix8bRampNoLoop(voice_t *v, uint32_t bufferPos, uint32_t numSamples) { const int8_t *base, *smpPtr; @@ -1353,6 +1532,218 @@ void centerMix8bRampBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t nu SET_BACK_MIXER_POS } +void centerMix8bRampNoLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int8_t *base, *smpPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + float fVolumeLDelta, fVolumeL; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac; + + GET_VOL_MONO_RAMP + GET_MIXER_VARS_MONO_RAMP + SET_BASE8 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + LIMIT_MIX_NUM_MONO_RAMP + samplesLeft -= samplesToMix; + + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + RENDER_8BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + RENDER_8BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + RENDER_8BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + } + + HANDLE_SAMPLE_END + } + + SET_VOL_BACK_MONO + SET_BACK_MIXER_POS +} + +void centerMix8bRampLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int8_t *base, *smpPtr; + int8_t *smpTapPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + float fVolumeLDelta, fVolumeL; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac; + + GET_VOL_MONO_RAMP + GET_MIXER_VARS_MONO_RAMP + SET_BASE8 + PREPARE_TAP_FIX8 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + LIMIT_MIX_NUM_MONO_RAMP + samplesLeft -= samplesToMix; + + if (v->hasLooped) // the negative interpolation taps need a special case after the sample has looped once + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS + } + } + else + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + RENDER_8BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + RENDER_8BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + RENDER_8BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + } + } + + WRAP_LOOP + } + + SET_VOL_BACK_MONO + SET_BACK_MIXER_POS +} + +void centerMix8bRampBidiLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int8_t *base, *revBase, *smpPtr; + int8_t *smpTapPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + float fVolumeLDelta, fVolumeL; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac, tmpDelta; + + GET_VOL_MONO_RAMP + GET_MIXER_VARS_MONO_RAMP + SET_BASE8_BIDI + PREPARE_TAP_FIX8 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + LIMIT_MIX_NUM_MONO_RAMP + samplesLeft -= samplesToMix; + + START_BIDI + if (v->hasLooped) // the negative interpolation taps need a special case after the sample has looped once + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS_BIDI + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS_BIDI + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS_BIDI + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS_BIDI + RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS_BIDI + } + } + else + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS_BIDI + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS_BIDI + RENDER_8BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS_BIDI + RENDER_8BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS_BIDI + RENDER_8BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS_BIDI + } + } + END_BIDI + + WRAP_BIDI_LOOP + } + + SET_VOL_BACK_MONO + SET_BACK_MIXER_POS +} + /* ----------------------------------------------------------------------- */ /* 16-BIT CENTER MIXING ROUTINES */ /* ----------------------------------------------------------------------- */ @@ -1771,17 +2162,195 @@ void centerMix16bBidiLoopLIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamp RENDER_16BIT_SMP_MONO_LINTRP INC_POS_BIDI } - samplesToMix >>= 2; - for (i = 0; i < samplesToMix; i++) + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_MONO_LINTRP + INC_POS_BIDI + RENDER_16BIT_SMP_MONO_LINTRP + INC_POS_BIDI + RENDER_16BIT_SMP_MONO_LINTRP + INC_POS_BIDI + RENDER_16BIT_SMP_MONO_LINTRP + INC_POS_BIDI + } + END_BIDI + + WRAP_BIDI_LOOP + } + + SET_BACK_MIXER_POS +} + +void centerMix16bNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int16_t *base, *smpPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac; + + GET_VOL_MONO + GET_MIXER_VARS + SET_BASE16 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + samplesLeft -= samplesToMix; + + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_MONO_S16INTRP + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_MONO_S16INTRP + INC_POS + RENDER_16BIT_SMP_MONO_S16INTRP + INC_POS + RENDER_16BIT_SMP_MONO_S16INTRP + INC_POS + RENDER_16BIT_SMP_MONO_S16INTRP + INC_POS + } + + HANDLE_SAMPLE_END + } + + SET_BACK_MIXER_POS +} + +void centerMix16bLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int16_t *base, *smpPtr; + int16_t *smpTapPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac; + + GET_VOL_MONO + GET_MIXER_VARS + SET_BASE16 + PREPARE_TAP_FIX16 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + samplesLeft -= samplesToMix; + + if (v->hasLooped) // the negative interpolation taps need a special case after the sample has looped once + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + INC_POS + RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + INC_POS + RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + INC_POS + RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + INC_POS + } + } + else + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_MONO_S16INTRP + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_MONO_S16INTRP + INC_POS + RENDER_16BIT_SMP_MONO_S16INTRP + INC_POS + RENDER_16BIT_SMP_MONO_S16INTRP + INC_POS + RENDER_16BIT_SMP_MONO_S16INTRP + INC_POS + } + } + + WRAP_LOOP + } + + SET_BACK_MIXER_POS +} + +void centerMix16bBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int16_t *base, *revBase, *smpPtr; + int16_t *smpTapPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac, tmpDelta; + + GET_VOL_MONO + GET_MIXER_VARS + SET_BASE16_BIDI + PREPARE_TAP_FIX16 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + samplesLeft -= samplesToMix; + + START_BIDI + if (v->hasLooped) // the negative interpolation taps need a special case after the sample has looped once + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + INC_POS_BIDI + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + INC_POS_BIDI + RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + INC_POS_BIDI + RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + INC_POS_BIDI + RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + INC_POS_BIDI + } + } + else { - RENDER_16BIT_SMP_MONO_LINTRP - INC_POS_BIDI - RENDER_16BIT_SMP_MONO_LINTRP - INC_POS_BIDI - RENDER_16BIT_SMP_MONO_LINTRP - INC_POS_BIDI - RENDER_16BIT_SMP_MONO_LINTRP - INC_POS_BIDI + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_MONO_S16INTRP + INC_POS_BIDI + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_MONO_S16INTRP + INC_POS_BIDI + RENDER_16BIT_SMP_MONO_S16INTRP + INC_POS_BIDI + RENDER_16BIT_SMP_MONO_S16INTRP + INC_POS_BIDI + RENDER_16BIT_SMP_MONO_S16INTRP + INC_POS_BIDI + } } END_BIDI @@ -1791,7 +2360,7 @@ void centerMix16bBidiLoopLIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamp SET_BACK_MIXER_POS } -void centerMix16bNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +void centerMix16bNoLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) { const int16_t *base, *smpPtr; float fSample, *fMixBufferL, *fMixBufferR; @@ -1811,19 +2380,19 @@ void centerMix16bNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamp for (i = 0; i < (samplesToMix & 3); i++) { - RENDER_16BIT_SMP_MONO_S16INTRP + RENDER_16BIT_SMP_MONO_CINTRP INC_POS } samplesToMix >>= 2; for (i = 0; i < samplesToMix; i++) { - RENDER_16BIT_SMP_MONO_S16INTRP + RENDER_16BIT_SMP_MONO_CINTRP INC_POS - RENDER_16BIT_SMP_MONO_S16INTRP + RENDER_16BIT_SMP_MONO_CINTRP INC_POS - RENDER_16BIT_SMP_MONO_S16INTRP + RENDER_16BIT_SMP_MONO_CINTRP INC_POS - RENDER_16BIT_SMP_MONO_S16INTRP + RENDER_16BIT_SMP_MONO_CINTRP INC_POS } @@ -1833,7 +2402,7 @@ void centerMix16bNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamp SET_BACK_MIXER_POS } -void centerMix16bLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +void centerMix16bLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) { const int16_t *base, *smpPtr; int16_t *smpTapPtr; @@ -1857,19 +2426,19 @@ void centerMix16bLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSample { for (i = 0; i < (samplesToMix & 3); i++) { - RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX INC_POS } samplesToMix >>= 2; for (i = 0; i < samplesToMix; i++) { - RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX INC_POS - RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX INC_POS - RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX INC_POS - RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX INC_POS } } @@ -1877,19 +2446,19 @@ void centerMix16bLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSample { for (i = 0; i < (samplesToMix & 3); i++) { - RENDER_16BIT_SMP_MONO_S16INTRP + RENDER_16BIT_SMP_MONO_CINTRP INC_POS } samplesToMix >>= 2; for (i = 0; i < samplesToMix; i++) { - RENDER_16BIT_SMP_MONO_S16INTRP + RENDER_16BIT_SMP_MONO_CINTRP INC_POS - RENDER_16BIT_SMP_MONO_S16INTRP + RENDER_16BIT_SMP_MONO_CINTRP INC_POS - RENDER_16BIT_SMP_MONO_S16INTRP + RENDER_16BIT_SMP_MONO_CINTRP INC_POS - RENDER_16BIT_SMP_MONO_S16INTRP + RENDER_16BIT_SMP_MONO_CINTRP INC_POS } } @@ -1900,7 +2469,7 @@ void centerMix16bLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSample SET_BACK_MIXER_POS } -void centerMix16bBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +void centerMix16bBidiLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) { const int16_t *base, *revBase, *smpPtr; int16_t *smpTapPtr; @@ -1925,19 +2494,19 @@ void centerMix16bBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSa { for (i = 0; i < (samplesToMix & 3); i++) { - RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX INC_POS_BIDI } samplesToMix >>= 2; for (i = 0; i < samplesToMix; i++) { - RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX INC_POS_BIDI - RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX INC_POS_BIDI - RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX INC_POS_BIDI - RENDER_16BIT_SMP_MONO_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX INC_POS_BIDI } } @@ -1945,19 +2514,19 @@ void centerMix16bBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSa { for (i = 0; i < (samplesToMix & 3); i++) { - RENDER_16BIT_SMP_MONO_S16INTRP + RENDER_16BIT_SMP_MONO_CINTRP INC_POS_BIDI } samplesToMix >>= 2; for (i = 0; i < samplesToMix; i++) { - RENDER_16BIT_SMP_MONO_S16INTRP + RENDER_16BIT_SMP_MONO_CINTRP INC_POS_BIDI - RENDER_16BIT_SMP_MONO_S16INTRP + RENDER_16BIT_SMP_MONO_CINTRP INC_POS_BIDI - RENDER_16BIT_SMP_MONO_S16INTRP + RENDER_16BIT_SMP_MONO_CINTRP INC_POS_BIDI - RENDER_16BIT_SMP_MONO_S16INTRP + RENDER_16BIT_SMP_MONO_CINTRP INC_POS_BIDI } } @@ -2696,3 +3265,215 @@ void centerMix16bRampBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t n SET_VOL_BACK_MONO SET_BACK_MIXER_POS } + +void centerMix16bRampNoLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int16_t *base, *smpPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + float fVolumeLDelta, fVolumeL; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac; + + GET_VOL_MONO_RAMP + GET_MIXER_VARS_MONO_RAMP + SET_BASE16 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + LIMIT_MIX_NUM_MONO_RAMP + samplesLeft -= samplesToMix; + + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + RENDER_16BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + RENDER_16BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + RENDER_16BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + } + + HANDLE_SAMPLE_END + } + + SET_VOL_BACK_MONO + SET_BACK_MIXER_POS +} + +void centerMix16bRampLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int16_t *base, *smpPtr; + int16_t *smpTapPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + float fVolumeLDelta, fVolumeL; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac; + + GET_VOL_MONO_RAMP + GET_MIXER_VARS_MONO_RAMP + SET_BASE16 + PREPARE_TAP_FIX16 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + LIMIT_MIX_NUM_MONO_RAMP + samplesLeft -= samplesToMix; + + if (v->hasLooped) // the negative interpolation taps need a special case after the sample has looped once + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS + } + } + else + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + RENDER_16BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + RENDER_16BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + RENDER_16BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS + } + } + + WRAP_LOOP + } + + SET_VOL_BACK_MONO + SET_BACK_MIXER_POS +} + +void centerMix16bRampBidiLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int16_t *base, *revBase, *smpPtr; + int16_t *smpTapPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + float fVolumeLDelta, fVolumeL; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac, tmpDelta; + + GET_VOL_MONO_RAMP + GET_MIXER_VARS_MONO_RAMP + SET_BASE16_BIDI + PREPARE_TAP_FIX16 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + LIMIT_MIX_NUM_MONO_RAMP + samplesLeft -= samplesToMix; + + START_BIDI + if (v->hasLooped) // the negative interpolation taps need a special case after the sample has looped once + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS_BIDI + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS_BIDI + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS_BIDI + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS_BIDI + RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX + VOLUME_RAMPING_MONO + INC_POS_BIDI + } + } + else + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS_BIDI + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS_BIDI + RENDER_16BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS_BIDI + RENDER_16BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS_BIDI + RENDER_16BIT_SMP_MONO_CINTRP + VOLUME_RAMPING_MONO + INC_POS_BIDI + } + } + END_BIDI + + WRAP_BIDI_LOOP + } + + SET_VOL_BACK_MONO + SET_BACK_MIXER_POS +} diff --git a/src/mixer/ft2_center_mix.h b/src/mixer/ft2_center_mix.h @@ -18,6 +18,9 @@ void centerMix8bBidiLoopLIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSampl void centerMix8bNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); void centerMix8bLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); void centerMix8bBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); +void centerMix8bNoLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); +void centerMix8bLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); +void centerMix8bBidiLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); // 16-bit void centerMix16bNoLoop(voice_t *v, uint32_t bufferPos, uint32_t numSamples); @@ -32,6 +35,9 @@ void centerMix16bBidiLoopLIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamp void centerMix16bNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); void centerMix16bLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); void centerMix16bBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); +void centerMix16bNoLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); +void centerMix16bLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); +void centerMix16bBidiLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); // volume ramping @@ -48,6 +54,9 @@ void centerMix8bRampBidiLoopLIntrp(voice_t *v, uint32_t bufferPos, uint32_t numS void centerMix8bRampNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); void centerMix8bRampLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); void centerMix8bRampBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); +void centerMix8bRampNoLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); +void centerMix8bRampLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); +void centerMix8bRampBidiLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); // 16bit void centerMix16bRampNoLoop(voice_t *v, uint32_t bufferPos, uint32_t numSamples); @@ -62,3 +71,6 @@ void centerMix16bRampBidiLoopLIntrp(voice_t *v, uint32_t bufferPos, uint32_t num void centerMix16bRampNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); void centerMix16bRampLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); void centerMix16bRampBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); +void centerMix16bRampNoLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); +void centerMix16bRampLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); +void centerMix16bRampBidiLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples); diff --git a/src/mixer/ft2_cubic_spline.c b/src/mixer/ft2_cubic_spline.c @@ -0,0 +1,41 @@ +#include <stdint.h> +#include <stdbool.h> +#include <stdlib.h> +#include "ft2_cubic_spline.h" +#include "../ft2_video.h" // showErrorMsgBox() + +float *fCubicSplineLUT = NULL; // globalized + +bool calcCubicSplineTable(void) +{ + fCubicSplineLUT = (float *)malloc(CUBIC_SPLINE_TAPS*CUBIC_SPLINE_PHASES * sizeof (float)); + if (fCubicSplineLUT == NULL) + { + showErrorMsgBox("Not enough memory!"); + return false; + } + + float *fPtr = fCubicSplineLUT; + for (int32_t i = 0; i < CUBIC_SPLINE_PHASES; i++) + { + const double x = i * (1.0 / CUBIC_SPLINE_PHASES); // x = i / CUBIC_SPLINE_PHASES + const double x2 = x * x; // x^2 + const double x3 = x2 * x; // x^3 + + *fPtr++ = (float)(-0.5 * x3 + 1.0 * x2 - 0.5 * x); + *fPtr++ = (float)( 1.5 * x3 - 2.5 * x2 + 1.0); + *fPtr++ = (float)(-1.5 * x3 + 2.0 * x2 + 0.5 * x); + *fPtr++ = (float)( 0.5 * x3 - 0.5 * x2); + } + + return true; +} + +void freeCubicSplineTable(void) +{ + if (fCubicSplineLUT != NULL) + { + free(fCubicSplineLUT); + fCubicSplineLUT = NULL; + } +} diff --git a/src/mixer/ft2_cubic_spline.h b/src/mixer/ft2_cubic_spline.h @@ -0,0 +1,21 @@ +#pragma once + +#include <stdint.h> +#include <stdbool.h> +#include "ft2_mix.h" // MIXER_FRAC_BITS + +#define CUBIC_SPLINE_TAPS 4 +#define CUBIC_WIDTH_BITS 2 + +// 8192 is a good compromise +#define CUBIC_SPLINE_PHASES 8192 +#define CUBIC_SPLINE_PHASES_BITS 13 // log2(CUBIC_PHASES) + +// do not change these! +#define CUBIC_SPLINE_FSHIFT (MIXER_FRAC_BITS-(CUBIC_SPLINE_PHASES_BITS+CUBIC_WIDTH_BITS)) +#define CUBIC_SPLINE_FMASK ((CUBIC_SPLINE_TAPS*CUBIC_SPLINE_PHASES)-CUBIC_SPLINE_TAPS) + +extern float *fCubicSplineLUT; + +bool calcCubicSplineTable(void); +void freeCubicSplineTable(void); diff --git a/src/mixer/ft2_mix.c b/src/mixer/ft2_mix.c @@ -10,13 +10,13 @@ ** (Note: Mixing macros can be found in ft2_mix_macros.h) ** ** Specifications: -** - Interpolation: None, 2-tap linear, 8-tap windowed-sinc, 16-tap windowed-sinc +** - Interpolation: None, 2-tap linear, 4-tap cubic spline, 8-tap windowed-sinc, 16-tap windowed-sinc ** - FT2-styled linear volume ramping (can be turned off) ** - 32.32 (16.16 if 32-bit CPU) fixed-point precision for resampling delta/position ** - 32-bit floating-point precision for mixing and interpolation ** ** This file has separate routines for EVERY possible sampling variation: -** Interpolation none/sinc/linear, volumeramp on/off, 8-bit, 16-bit, no loop, loop, bidi. +** Interpolation none/sinc/linear/cubic, volumeramp on/off, 8-bit, 16-bit, no loop, loop, bidi. ** (36 mixing routines in total + another 36 for center-mixing) ** ** Every voice has a function pointer set to the according mixing routine on @@ -643,6 +643,184 @@ static void mix8bBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSa SET_BACK_MIXER_POS } +static void mix8bNoLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int8_t *base, *smpPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac; + + GET_VOL + GET_MIXER_VARS + SET_BASE8 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + samplesLeft -= samplesToMix; + + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_CINTRP + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_CINTRP + INC_POS + RENDER_8BIT_SMP_CINTRP + INC_POS + RENDER_8BIT_SMP_CINTRP + INC_POS + RENDER_8BIT_SMP_CINTRP + INC_POS + } + + HANDLE_SAMPLE_END + } + + SET_BACK_MIXER_POS +} + +static void mix8bLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int8_t *base, *smpPtr; + int8_t *smpTapPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac; + + GET_VOL + GET_MIXER_VARS + SET_BASE8 + PREPARE_TAP_FIX8 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + samplesLeft -= samplesToMix; + + if (v->hasLooped) // the negative interpolation taps need a special case after the sample has looped once + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_CINTRP_TAP_FIX + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_CINTRP_TAP_FIX + INC_POS + RENDER_8BIT_SMP_CINTRP_TAP_FIX + INC_POS + RENDER_8BIT_SMP_CINTRP_TAP_FIX + INC_POS + RENDER_8BIT_SMP_CINTRP_TAP_FIX + INC_POS + } + } + else + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_CINTRP + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_CINTRP + INC_POS + RENDER_8BIT_SMP_CINTRP + INC_POS + RENDER_8BIT_SMP_CINTRP + INC_POS + RENDER_8BIT_SMP_CINTRP + INC_POS + } + } + + WRAP_LOOP + } + + SET_BACK_MIXER_POS +} + +static void mix8bBidiLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int8_t *base, *revBase, *smpPtr; + int8_t *smpTapPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac, tmpDelta; + + GET_VOL + GET_MIXER_VARS + SET_BASE8_BIDI + PREPARE_TAP_FIX8 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + samplesLeft -= samplesToMix; + + START_BIDI + if (v->hasLooped) // the negative interpolation taps need a special case after the sample has looped once + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_CINTRP_TAP_FIX + INC_POS_BIDI + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_CINTRP_TAP_FIX + INC_POS_BIDI + RENDER_8BIT_SMP_CINTRP_TAP_FIX + INC_POS_BIDI + RENDER_8BIT_SMP_CINTRP_TAP_FIX + INC_POS_BIDI + RENDER_8BIT_SMP_CINTRP_TAP_FIX + INC_POS_BIDI + } + } + else + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_CINTRP + INC_POS_BIDI + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_CINTRP + INC_POS_BIDI + RENDER_8BIT_SMP_CINTRP + INC_POS_BIDI + RENDER_8BIT_SMP_CINTRP + INC_POS_BIDI + RENDER_8BIT_SMP_CINTRP + INC_POS_BIDI + } + } + END_BIDI + + WRAP_BIDI_LOOP + } + + SET_BACK_MIXER_POS +} + static void mix8bRampNoLoop(voice_t *v, uint32_t bufferPos, uint32_t numSamples) { const int8_t *base, *smpPtr; @@ -1371,6 +1549,218 @@ static void mix8bRampBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t n SET_BACK_MIXER_POS } +static void mix8bRampNoLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int8_t *base, *smpPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac; + + GET_VOL_RAMP + GET_MIXER_VARS_RAMP + SET_BASE8 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + LIMIT_MIX_NUM_RAMP + samplesLeft -= samplesToMix; + + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + RENDER_8BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + RENDER_8BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + RENDER_8BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + } + + HANDLE_SAMPLE_END + } + + SET_VOL_BACK + SET_BACK_MIXER_POS +} + +static void mix8bRampLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int8_t *base, *smpPtr; + int8_t *smpTapPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac; + + GET_VOL_RAMP + GET_MIXER_VARS_RAMP + SET_BASE8 + PREPARE_TAP_FIX8 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + LIMIT_MIX_NUM_RAMP + samplesLeft -= samplesToMix; + + if (v->hasLooped) // the negative interpolation taps need a special case after the sample has looped once + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS + RENDER_8BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS + RENDER_8BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS + RENDER_8BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS + } + } + else + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + RENDER_8BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + RENDER_8BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + RENDER_8BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + } + } + + WRAP_LOOP + } + + SET_VOL_BACK + SET_BACK_MIXER_POS +} + +static void mix8bRampBidiLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int8_t *base, *revBase, *smpPtr; + int8_t *smpTapPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac, tmpDelta; + + GET_VOL_RAMP + GET_MIXER_VARS_RAMP + SET_BASE8_BIDI + PREPARE_TAP_FIX8 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + LIMIT_MIX_NUM_RAMP + samplesLeft -= samplesToMix; + + START_BIDI + if (v->hasLooped) // the negative interpolation taps need a special case after the sample has looped once + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS_BIDI + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS_BIDI + RENDER_8BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS_BIDI + RENDER_8BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS_BIDI + RENDER_8BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS_BIDI + } + } + else + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_8BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS_BIDI + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_8BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS_BIDI + RENDER_8BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS_BIDI + RENDER_8BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS_BIDI + RENDER_8BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS_BIDI + } + } + END_BIDI + + WRAP_BIDI_LOOP + } + + SET_VOL_BACK + SET_BACK_MIXER_POS +} + /* ----------------------------------------------------------------------- */ /* 16-BIT MIXING ROUTINES */ /* ----------------------------------------------------------------------- */ @@ -1789,17 +2179,195 @@ static void mix16bBidiLoopLIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSam RENDER_16BIT_SMP_LINTRP INC_POS_BIDI } - samplesToMix >>= 2; - for (i = 0; i < samplesToMix; i++) + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_LINTRP + INC_POS_BIDI + RENDER_16BIT_SMP_LINTRP + INC_POS_BIDI + RENDER_16BIT_SMP_LINTRP + INC_POS_BIDI + RENDER_16BIT_SMP_LINTRP + INC_POS_BIDI + } + END_BIDI + + WRAP_BIDI_LOOP + } + + SET_BACK_MIXER_POS +} + +static void mix16bNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int16_t *base, *smpPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac; + + GET_VOL + GET_MIXER_VARS + SET_BASE16 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + samplesLeft -= samplesToMix; + + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_S16INTRP + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_S16INTRP + INC_POS + RENDER_16BIT_SMP_S16INTRP + INC_POS + RENDER_16BIT_SMP_S16INTRP + INC_POS + RENDER_16BIT_SMP_S16INTRP + INC_POS + } + + HANDLE_SAMPLE_END + } + + SET_BACK_MIXER_POS +} + +static void mix16bLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int16_t *base, *smpPtr; + int16_t *smpTapPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac; + + GET_VOL + GET_MIXER_VARS + SET_BASE16 + PREPARE_TAP_FIX16 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + samplesLeft -= samplesToMix; + + if (v->hasLooped) // the negative interpolation taps need a special case after the sample has looped once + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_S16INTRP_TAP_FIX + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_S16INTRP_TAP_FIX + INC_POS + RENDER_16BIT_SMP_S16INTRP_TAP_FIX + INC_POS + RENDER_16BIT_SMP_S16INTRP_TAP_FIX + INC_POS + RENDER_16BIT_SMP_S16INTRP_TAP_FIX + INC_POS + } + } + else + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_S16INTRP + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_S16INTRP + INC_POS + RENDER_16BIT_SMP_S16INTRP + INC_POS + RENDER_16BIT_SMP_S16INTRP + INC_POS + RENDER_16BIT_SMP_S16INTRP + INC_POS + } + } + + WRAP_LOOP + } + + SET_BACK_MIXER_POS +} + +static void mix16bBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int16_t *base, *revBase, *smpPtr; + int16_t *smpTapPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac, tmpDelta; + + GET_VOL + GET_MIXER_VARS + SET_BASE16_BIDI + PREPARE_TAP_FIX16 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + samplesLeft -= samplesToMix; + + START_BIDI + if (v->hasLooped) // the negative interpolation taps need a special case after the sample has looped once + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_S16INTRP_TAP_FIX + INC_POS_BIDI + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_S16INTRP_TAP_FIX + INC_POS_BIDI + RENDER_16BIT_SMP_S16INTRP_TAP_FIX + INC_POS_BIDI + RENDER_16BIT_SMP_S16INTRP_TAP_FIX + INC_POS_BIDI + RENDER_16BIT_SMP_S16INTRP_TAP_FIX + INC_POS_BIDI + } + } + else { - RENDER_16BIT_SMP_LINTRP - INC_POS_BIDI - RENDER_16BIT_SMP_LINTRP - INC_POS_BIDI - RENDER_16BIT_SMP_LINTRP - INC_POS_BIDI - RENDER_16BIT_SMP_LINTRP - INC_POS_BIDI + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_S16INTRP + INC_POS_BIDI + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_S16INTRP + INC_POS_BIDI + RENDER_16BIT_SMP_S16INTRP + INC_POS_BIDI + RENDER_16BIT_SMP_S16INTRP + INC_POS_BIDI + RENDER_16BIT_SMP_S16INTRP + INC_POS_BIDI + } } END_BIDI @@ -1809,7 +2377,7 @@ static void mix16bBidiLoopLIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSam SET_BACK_MIXER_POS } -static void mix16bNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +static void mix16bNoLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) { const int16_t *base, *smpPtr; float fSample, *fMixBufferL, *fMixBufferR; @@ -1829,19 +2397,19 @@ static void mix16bNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSam for (i = 0; i < (samplesToMix & 3); i++) { - RENDER_16BIT_SMP_S16INTRP + RENDER_16BIT_SMP_CINTRP INC_POS } samplesToMix >>= 2; for (i = 0; i < samplesToMix; i++) { - RENDER_16BIT_SMP_S16INTRP + RENDER_16BIT_SMP_CINTRP INC_POS - RENDER_16BIT_SMP_S16INTRP + RENDER_16BIT_SMP_CINTRP INC_POS - RENDER_16BIT_SMP_S16INTRP + RENDER_16BIT_SMP_CINTRP INC_POS - RENDER_16BIT_SMP_S16INTRP + RENDER_16BIT_SMP_CINTRP INC_POS } @@ -1851,7 +2419,7 @@ static void mix16bNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSam SET_BACK_MIXER_POS } -static void mix16bLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +static void mix16bLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) { const int16_t *base, *smpPtr; int16_t *smpTapPtr; @@ -1875,19 +2443,19 @@ static void mix16bLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSampl { for (i = 0; i < (samplesToMix & 3); i++) { - RENDER_16BIT_SMP_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_CINTRP_TAP_FIX INC_POS } samplesToMix >>= 2; for (i = 0; i < samplesToMix; i++) { - RENDER_16BIT_SMP_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_CINTRP_TAP_FIX INC_POS - RENDER_16BIT_SMP_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_CINTRP_TAP_FIX INC_POS - RENDER_16BIT_SMP_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_CINTRP_TAP_FIX INC_POS - RENDER_16BIT_SMP_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_CINTRP_TAP_FIX INC_POS } } @@ -1895,19 +2463,19 @@ static void mix16bLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSampl { for (i = 0; i < (samplesToMix & 3); i++) { - RENDER_16BIT_SMP_S16INTRP + RENDER_16BIT_SMP_CINTRP INC_POS } samplesToMix >>= 2; for (i = 0; i < samplesToMix; i++) { - RENDER_16BIT_SMP_S16INTRP + RENDER_16BIT_SMP_CINTRP INC_POS - RENDER_16BIT_SMP_S16INTRP + RENDER_16BIT_SMP_CINTRP INC_POS - RENDER_16BIT_SMP_S16INTRP + RENDER_16BIT_SMP_CINTRP INC_POS - RENDER_16BIT_SMP_S16INTRP + RENDER_16BIT_SMP_CINTRP INC_POS } } @@ -1918,7 +2486,7 @@ static void mix16bLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSampl SET_BACK_MIXER_POS } -static void mix16bBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +static void mix16bBidiLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) { const int16_t *base, *revBase, *smpPtr; int16_t *smpTapPtr; @@ -1943,19 +2511,19 @@ static void mix16bBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numS { for (i = 0; i < (samplesToMix & 3); i++) { - RENDER_16BIT_SMP_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_CINTRP_TAP_FIX INC_POS_BIDI } samplesToMix >>= 2; for (i = 0; i < samplesToMix; i++) { - RENDER_16BIT_SMP_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_CINTRP_TAP_FIX INC_POS_BIDI - RENDER_16BIT_SMP_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_CINTRP_TAP_FIX INC_POS_BIDI - RENDER_16BIT_SMP_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_CINTRP_TAP_FIX INC_POS_BIDI - RENDER_16BIT_SMP_S16INTRP_TAP_FIX + RENDER_16BIT_SMP_CINTRP_TAP_FIX INC_POS_BIDI } } @@ -1963,19 +2531,19 @@ static void mix16bBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numS { for (i = 0; i < (samplesToMix & 3); i++) { - RENDER_16BIT_SMP_S16INTRP + RENDER_16BIT_SMP_CINTRP INC_POS_BIDI } samplesToMix >>= 2; for (i = 0; i < samplesToMix; i++) { - RENDER_16BIT_SMP_S16INTRP + RENDER_16BIT_SMP_CINTRP INC_POS_BIDI - RENDER_16BIT_SMP_S16INTRP + RENDER_16BIT_SMP_CINTRP INC_POS_BIDI - RENDER_16BIT_SMP_S16INTRP + RENDER_16BIT_SMP_CINTRP INC_POS_BIDI - RENDER_16BIT_SMP_S16INTRP + RENDER_16BIT_SMP_CINTRP INC_POS_BIDI } } @@ -2715,6 +3283,218 @@ static void mix16bRampBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t SET_BACK_MIXER_POS } +static void mix16bRampNoLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int16_t *base, *smpPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac; + + GET_VOL_RAMP + GET_MIXER_VARS_RAMP + SET_BASE16 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + LIMIT_MIX_NUM_RAMP + samplesLeft -= samplesToMix; + + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + RENDER_16BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + RENDER_16BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + RENDER_16BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + } + + HANDLE_SAMPLE_END + } + + SET_VOL_BACK + SET_BACK_MIXER_POS +} + +static void mix16bRampLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int16_t *base, *smpPtr; + int16_t *smpTapPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac; + + GET_VOL_RAMP + GET_MIXER_VARS_RAMP + SET_BASE16 + PREPARE_TAP_FIX16 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + LIMIT_MIX_NUM_RAMP + samplesLeft -= samplesToMix; + + if (v->hasLooped) // the negative interpolation taps need a special case after the sample has looped once + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS + RENDER_16BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS + RENDER_16BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS + RENDER_16BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS + } + } + else + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + RENDER_16BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + RENDER_16BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + RENDER_16BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS + } + } + + WRAP_LOOP + } + + SET_VOL_BACK + SET_BACK_MIXER_POS +} + +static void mix16bRampBidiLoopCIntrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples) +{ + const int16_t *base, *revBase, *smpPtr; + int16_t *smpTapPtr; + float fSample, *fMixBufferL, *fMixBufferR; + int32_t position; + float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR; + uint32_t i, samplesToMix, samplesLeft; + uintCPUWord_t positionFrac, tmpDelta; + + GET_VOL_RAMP + GET_MIXER_VARS_RAMP + SET_BASE16_BIDI + PREPARE_TAP_FIX16 + + samplesLeft = numSamples; + while (samplesLeft > 0) + { + LIMIT_MIX_NUM + LIMIT_MIX_NUM_RAMP + samplesLeft -= samplesToMix; + + START_BIDI + if (v->hasLooped) // the negative interpolation taps need a special case after the sample has looped once + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS_BIDI + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS_BIDI + RENDER_16BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS_BIDI + RENDER_16BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS_BIDI + RENDER_16BIT_SMP_CINTRP_TAP_FIX + VOLUME_RAMPING + INC_POS_BIDI + } + } + else + { + for (i = 0; i < (samplesToMix & 3); i++) + { + RENDER_16BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS_BIDI + } + samplesToMix >>= 2; + for (i = 0; i < samplesToMix; i++) + { + RENDER_16BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS_BIDI + RENDER_16BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS_BIDI + RENDER_16BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS_BIDI + RENDER_16BIT_SMP_CINTRP + VOLUME_RAMPING + INC_POS_BIDI + } + } + END_BIDI + + WRAP_BIDI_LOOP + } + + SET_VOL_BACK + SET_BACK_MIXER_POS +} + // ----------------------------------------------------------------------- const mixFunc mixFuncTab[] = @@ -2740,6 +3520,9 @@ const mixFunc mixFuncTab[] = (mixFunc)mix8bNoLoopS16Intrp, (mixFunc)mix8bLoopS16Intrp, (mixFunc)mix8bBidiLoopS16Intrp, + (mixFunc)mix8bNoLoopCIntrp, + (mixFunc)mix8bLoopCIntrp, + (mixFunc)mix8bBidiLoopCIntrp, // 16-bit (mixFunc)mix16bNoLoop, @@ -2754,6 +3537,9 @@ const mixFunc mixFuncTab[] = (mixFunc)mix16bNoLoopS16Intrp, (mixFunc)mix16bLoopS16Intrp, (mixFunc)mix16bBidiLoopS16Intrp, + (mixFunc)mix16bNoLoopCIntrp, + (mixFunc)mix16bLoopCIntrp, + (mixFunc)mix16bBidiLoopCIntrp, // volume ramping @@ -2770,6 +3556,9 @@ const mixFunc mixFuncTab[] = (mixFunc)mix8bRampNoLoopS16Intrp, (mixFunc)mix8bRampLoopS16Intrp, (mixFunc)mix8bRampBidiLoopS16Intrp, + (mixFunc)mix8bRampNoLoopCIntrp, + (mixFunc)mix8bRampLoopCIntrp, + (mixFunc)mix8bRampBidiLoopCIntrp, // 16-bit (mixFunc)mix16bRampNoLoop, @@ -2784,6 +3573,9 @@ const mixFunc mixFuncTab[] = (mixFunc)mix16bRampNoLoopS16Intrp, (mixFunc)mix16bRampLoopS16Intrp, (mixFunc)mix16bRampBidiLoopS16Intrp, + (mixFunc)mix16bRampNoLoopCIntrp, + (mixFunc)mix16bRampLoopCIntrp, + (mixFunc)mix16bRampBidiLoopCIntrp, /* ** --------------------------------- @@ -2806,6 +3598,9 @@ const mixFunc mixFuncTab[] = (mixFunc)centerMix8bNoLoopS16Intrp, (mixFunc)centerMix8bLoopS16Intrp, (mixFunc)centerMix8bBidiLoopS16Intrp, + (mixFunc)centerMix8bNoLoopCIntrp, + (mixFunc)centerMix8bLoopCIntrp, + (mixFunc)centerMix8bBidiLoopCIntrp, // 16-bit (mixFunc)centerMix16bNoLoop, @@ -2820,6 +3615,9 @@ const mixFunc mixFuncTab[] = (mixFunc)centerMix16bNoLoopS16Intrp, (mixFunc)centerMix16bLoopS16Intrp, (mixFunc)centerMix16bBidiLoopS16Intrp, + (mixFunc)centerMix16bNoLoopCIntrp, + (mixFunc)centerMix16bLoopCIntrp, + (mixFunc)centerMix16bBidiLoopCIntrp, // volume ramping @@ -2836,6 +3634,9 @@ const mixFunc mixFuncTab[] = (mixFunc)centerMix8bRampNoLoopS16Intrp, (mixFunc)centerMix8bRampLoopS16Intrp, (mixFunc)centerMix8bRampBidiLoopS16Intrp, + (mixFunc)centerMix8bRampNoLoopCIntrp, + (mixFunc)centerMix8bRampLoopCIntrp, + (mixFunc)centerMix8bRampBidiLoopCIntrp, // 16-bit (mixFunc)centerMix16bRampNoLoop, @@ -2849,5 +3650,8 @@ const mixFunc mixFuncTab[] = (mixFunc)centerMix16bRampBidiLoopLIntrp, (mixFunc)centerMix16bRampNoLoopS16Intrp, (mixFunc)centerMix16bRampLoopS16Intrp, - (mixFunc)centerMix16bRampBidiLoopS16Intrp + (mixFunc)centerMix16bRampBidiLoopS16Intrp, + (mixFunc)centerMix16bRampNoLoopCIntrp, + (mixFunc)centerMix16bRampLoopCIntrp, + (mixFunc)centerMix16bRampBidiLoopCIntrp }; diff --git a/src/mixer/ft2_mix.h b/src/mixer/ft2_mix.h @@ -3,6 +3,10 @@ #include <stdint.h> #include "../ft2_cpu.h" +#define MAX_TAPS 16 +#define MAX_LEFT_TAPS ((MAX_TAPS/2)-1) +#define MAX_RIGHT_TAPS (MAX_TAPS/2) + // the fractional bits are hardcoded, changing these will break things! #if CPU_64BIT #define MIXER_FRAC_BITS 32 diff --git a/src/mixer/ft2_mix_macros.h b/src/mixer/ft2_mix_macros.h @@ -55,11 +55,11 @@ #define PREPARE_TAP_FIX8 \ const int8_t *loopStartPtr = &v->base8[v->loopStart]; \ - const int8_t *leftEdgePtr = loopStartPtr+SINC_MAX_LEFT_TAPS; + const int8_t *leftEdgePtr = loopStartPtr+MAX_LEFT_TAPS; #define PREPARE_TAP_FIX16 \ const int16_t *loopStartPtr = &v->base16[v->loopStart]; \ - const int16_t *leftEdgePtr = loopStartPtr+SINC_MAX_LEFT_TAPS; + const int16_t *leftEdgePtr = loopStartPtr+MAX_LEFT_TAPS; #define SET_BASE8 \ base = v->base8; \ @@ -123,7 +123,9 @@ *fMixBufferL++ += fSample; \ *fMixBufferR++ += fSample; -// 2-tap linear interpolation (like FT2) +/* ----------------------------------------------------------------------- */ +/* LINEAR INTERPOLATION */ +/* ----------------------------------------------------------------------- */ /* It may look like we are potentially going out of bounds while looking up the sample points, ** but the sample data has a fixed sample after the end (sampleEnd/loopEnd). @@ -158,7 +160,98 @@ *fMixBufferL++ += fSample; \ *fMixBufferR++ += fSample; -// windowed-sinc interpolation (better quality, through LUTs: mixer/ft2_windowed_sinc.c) +/* ----------------------------------------------------------------------- */ +/* CUBIC SPLINE INTERPOLATION */ +/* ----------------------------------------------------------------------- */ + +// through LUT: mixer/ft2_cubic_spline.c + +/* It may look like we are potentially going out of bounds while looking up the sample points, +** but the sample data is actually padded on both the left (negative) and right side, where correct tap +** samples are stored according to loop mode (or no loop). +** +** There is also a second special case for the left edge (negative taps) after the sample has looped once. +** +*/ + +#if CUBIC_FSHIFT>=0 +#define CUBIC_SPLINE_INTERPOLATION(s, f, scale) \ +{ \ + const float *t = fCubicSplineLUT + (((uint32_t)(f) >> CUBIC_SPLINE_FSHIFT) & CUBIC_SPLINE_FMASK); \ + fSample = ((s[-1] * t[0]) + \ + ( s[0] * t[1]) + \ + ( s[1] * t[2]) + \ + ( s[2] * t[3])) * (1.0f / scale); \ +} +#else +#define CUBIC_SPLINE_INTERPOLATION(s, f, scale) \ +{ \ + const float *t = fCubicSplineLUT + (((uint32_t)(f) << -CUBIC_SPLINE_FSHIFT) & CUBIC_SPLINE_FMASK); \ + fSample = ((s[-1] * t[0]) + \ + ( s[0] * t[1]) + \ + ( s[1] * t[2]) + \ + ( s[2] * t[3])) * (1.0f / scale); \ +} +#endif + +#define RENDER_8BIT_SMP_CINTRP \ + CUBIC_SPLINE_INTERPOLATION(smpPtr, positionFrac, 128) \ + *fMixBufferL++ += fSample * fVolumeL; \ + *fMixBufferR++ += fSample * fVolumeR; + +#define RENDER_8BIT_SMP_MONO_CINTRP \ + CUBIC_SPLINE_INTERPOLATION(smpPtr, positionFrac, 128) \ + fSample *= fVolumeL; \ + *fMixBufferL++ += fSample; \ + *fMixBufferR++ += fSample; + +#define RENDER_16BIT_SMP_CINTRP \ + CUBIC_SPLINE_INTERPOLATION(smpPtr, positionFrac, 32768) \ + *fMixBufferL++ += fSample * fVolumeL; \ + *fMixBufferR++ += fSample * fVolumeR; + +#define RENDER_16BIT_SMP_MONO_CINTRP \ + CUBIC_SPLINE_INTERPOLATION(smpPtr, positionFrac, 32768) \ + fSample *= fVolumeL; \ + *fMixBufferL++ += fSample; \ + *fMixBufferR++ += fSample; + + +/* Special left-edge case mixers to get proper tap data after one loop cycle. +** These are only used with cubic interpolation on looped samples. +*/ + +#define RENDER_8BIT_SMP_CINTRP_TAP_FIX \ + smpTapPtr = (smpPtr <= leftEdgePtr) ? (int8_t *)&v->leftEdgeTaps8[(int32_t)(smpPtr-loopStartPtr)] : (int8_t *)smpPtr; \ + CUBIC_SPLINE_INTERPOLATION(smpTapPtr, positionFrac, 128) \ + *fMixBufferL++ += fSample * fVolumeL; \ + *fMixBufferR++ += fSample * fVolumeR; + +#define RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX \ + smpTapPtr = (smpPtr <= leftEdgePtr) ? (int8_t *)&v->leftEdgeTaps8[(int32_t)(smpPtr-loopStartPtr)] : (int8_t *)smpPtr; \ + CUBIC_SPLINE_INTERPOLATION(smpTapPtr, positionFrac, 128) \ + fSample *= fVolumeL; \ + *fMixBufferL++ += fSample; \ + *fMixBufferR++ += fSample; + +#define RENDER_16BIT_SMP_CINTRP_TAP_FIX \ + smpTapPtr = (smpPtr <= leftEdgePtr) ? (int16_t *)&v->leftEdgeTaps16[(int32_t)(smpPtr-loopStartPtr)] : (int16_t *)smpPtr; \ + CUBIC_SPLINE_INTERPOLATION(smpTapPtr, positionFrac, 32768) \ + *fMixBufferL++ += fSample * fVolumeL; \ + *fMixBufferR++ += fSample * fVolumeR; + +#define RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX \ + smpTapPtr = (smpPtr <= leftEdgePtr) ? (int16_t *)&v->leftEdgeTaps16[(int32_t)(smpPtr-loopStartPtr)] : (int16_t *)smpPtr; \ + CUBIC_SPLINE_INTERPOLATION(smpTapPtr, positionFrac, 32768) \ + fSample *= fVolumeL; \ + *fMixBufferL++ += fSample; \ + *fMixBufferR++ += fSample; + +/* ----------------------------------------------------------------------- */ +/* WINDOWED-SINC INTERPOLATION */ +/* ----------------------------------------------------------------------- */ + +// through LUTs: mixer/ft2_windowed_sinc.c /* It may look like we are potentially going out of bounds while looking up the sample points, ** but the sample data is actually padded on both the left (negative) and right side, where correct tap diff --git a/src/mixer/ft2_windowed_sinc.h b/src/mixer/ft2_windowed_sinc.h @@ -9,13 +9,12 @@ #define SINC_PHASES_BITS 13 // log2(SINC_PHASES) // do not change these! -#define SINC8_FSHIFT (MIXER_FRAC_BITS-(SINC_PHASES_BITS+3)) +#define SINC8_WIDTH_BITS 3 // log2(8) +#define SINC8_FSHIFT (MIXER_FRAC_BITS-(SINC_PHASES_BITS+SINC8_WIDTH_BITS)) #define SINC8_FMASK ((8*SINC_PHASES)-8) -#define SINC16_FSHIFT (MIXER_FRAC_BITS-(SINC_PHASES_BITS+4)) +#define SINC16_WIDTH_BITS 4 // log2(16) +#define SINC16_FSHIFT (MIXER_FRAC_BITS-(SINC_PHASES_BITS+SINC16_WIDTH_BITS)) #define SINC16_FMASK ((16*SINC_PHASES)-16) -#define SINC_MAX_TAPS 16 -#define SINC_MAX_LEFT_TAPS ((SINC_MAX_TAPS/2)-1) -#define SINC_MAX_RIGHT_TAPS (SINC_MAX_TAPS/2) extern float *fKaiserSinc_8, *fDownSample1_8, *fDownSample2_8; extern float *fKaiserSinc_16, *fDownSample1_16, *fDownSample2_16; diff --git a/vs2019_project/ft2-clone/ft2-clone.vcxproj b/vs2019_project/ft2-clone/ft2-clone.vcxproj @@ -352,6 +352,7 @@ <ClCompile Include="..\..\src\libflac\stream_decoder.c" /> <ClCompile Include="..\..\src\libflac\window.c" /> <ClCompile Include="..\..\src\libflac\windows_unicode_filenames.c" /> + <ClCompile Include="..\..\src\mixer\ft2_cubic_spline.c" /> <ClCompile Include="..\..\src\mixer\ft2_windowed_sinc.c" /> <ClCompile Include="..\..\src\mixer\ft2_mix.c" /> <ClCompile Include="..\..\src\mixer\ft2_center_mix.c" /> @@ -426,6 +427,7 @@ <ClInclude Include="..\..\src\ft2_unicode.h" /> <ClInclude Include="..\..\src\ft2_video.h" /> <ClInclude Include="..\..\src\ft2_wav_renderer.h" /> + <ClInclude Include="..\..\src\mixer\ft2_cubic_spline.h" /> <ClInclude Include="..\..\src\mixer\ft2_windowed_sinc.h" /> <ClInclude Include="..\..\src\mixer\ft2_mix.h" /> <ClInclude Include="..\..\src\mixer\ft2_mix_macros.h" /> diff --git a/vs2019_project/ft2-clone/ft2-clone.vcxproj.filters b/vs2019_project/ft2-clone/ft2-clone.vcxproj.filters @@ -164,6 +164,9 @@ <Filter>scopes</Filter> </ClCompile> <ClCompile Include="..\..\src\ft2_hpc.c" /> + <ClCompile Include="..\..\src\mixer\ft2_cubic_spline.c"> + <Filter>mixer</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\src\rtmidi\RtMidi.h"> @@ -325,6 +328,9 @@ <ClInclude Include="..\..\src\ft2_hpc.h"> <Filter>headers</Filter> </ClInclude> + <ClInclude Include="..\..\src\mixer\ft2_cubic_spline.h"> + <Filter>mixer</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <Filter Include="mixer">