shithub: ft2-clone

Download patch

ref: 22c28f1c0de3a76cac067309abfd77f8d508c2bb
parent: 4e1aaeb982ef59dc209047651ef578f96963f03b
author: Olav Sørensen <olav.sorensen@live.no>
date: Fri Jun 12 12:32:01 EDT 2020

Pushed v1.25 code

- Instrument envelopes now show x/y coords in the top right corner in Instr. Ed.
- The song tempo (BPM) is now *slightly* more accurate for certain BPM values
- Fixed a bug with the XFade function on 16-bit pingpong samples

--- a/src/ft2_audio.c
+++ b/src/ft2_audio.c
@@ -24,9 +24,8 @@
 chSyncData_t *chSyncEntry;
 chSync_t chSync;
 pattSync_t pattSync;
-volatile bool pattQueueReading, pattQueueClearing, chQueueReading, chQueueClearing;
+volatile bool pattQueueClearing, chQueueClearing;
 
-
 static int8_t pmpCountDiv, pmpChannels = 2;
 static uint16_t smpBuffSize;
 static int32_t masterVol, oldAudioFreq, pmpLeft, randSeed = INITIAL_DITHER_SEED;
@@ -153,33 +152,22 @@
 
 void setSpeed(uint16_t bpm)
 {
-	double dInt, dFrac;
-
 	if (bpm == 0)
 		return;
 
-	audio.speedVal = ((audio.freq + audio.freq) + (audio.freq >> 1)) / bpm; // (audio.freq * 2.5) / BPM
-	if (audio.speedVal > 0) // calculate tick time length for audio/video sync timestamp
-	{
-		// number of samples per tick -> tick length for performance counter
-		dFrac = modf(audio.speedVal * audio.dSpeedValMul, &dInt);
+	// non-FT2 check for security
+	if (bpm > MAX_BPM)
+		return;
 
-		/* - integer part -
-		** Cast to int32_t so that the compiler will use fast SSE2 float->int instructions.
-		** This result won't be above 2^31, so this is safe.
-		*/
-		tickTimeLen = (int32_t)dInt;
+	audio.speedVal = audio.speedValTab[bpm];
 
-		// - fractional part (scaled to 0..2^32-1) -
-		dFrac *= UINT32_MAX;
-		dFrac += 0.5;
-		if (dFrac > UINT32_MAX)
-			dFrac = UINT32_MAX;
+	// get tick time length for audio/video sync timestamp
+	const uint64_t tickTimeLen64 = audio.tickTimeLengthTab[bpm];
+	tickTimeLen = tickTimeLen64 >> 32;
+	tickTimeLenFrac = tickTimeLen64 & 0xFFFFFFFF;
 
-		tickTimeLenFrac = (uint32_t)dFrac;
-
-		audio.rampSpeedValMul = 0xFFFFFFFF / audio.speedVal;
-	}
+	// used for calculating volume ramp length for "ticks" ramps
+	audio.rampSpeedValMul = audio.rampSpeedValMulTab[bpm];
 }
 
 void audioSetVolRamp(bool volRamp)
@@ -651,8 +639,8 @@
 		** read/write are two different threads, but because of timestamp validation it
 		** shouldn't be that dangerous.
 		** It will also create a small visual stutter while the buffer is getting filled,
-		** though that is barely noticable on normal buffer sizes, and it takes several
-		** minutes between each time (when queue size is default, 16384) */
+		** though that is barely noticable on normal buffer sizes, and it takes a minute
+		** or two at max BPM between each time (when queue size is default, 4095) */
 		pattSync.data[0].timestamp = 0;
 		pattSync.readPos = 0;
 		pattSync.writePos = 0;
@@ -878,16 +866,69 @@
 	audioPaused = false;
 }
 
-static void SDLCALL mixCallback(void *userdata, Uint8 *stream, int len)
+static void fillVisualsSyncBuffer(void)
 {
-	int32_t a, b;
 	pattSyncData_t pattSyncData;
 	chSyncData_t chSyncData;
 	syncedChannel_t *c;
 	stmTyp *s;
 
-	(void)userdata;
+	if (audio.resetSyncTickTimeFlag)
+	{
+		audio.resetSyncTickTimeFlag = false;
 
+		audio.tickTime64 = SDL_GetPerformanceCounter() + audio.audLatencyPerfValInt;
+		audio.tickTime64Frac = audio.audLatencyPerfValFrac;
+	}
+
+	if (songPlaying)
+	{
+		// push pattern variables to sync queue
+		pattSyncData.timer = song.curReplayerTimer;
+		pattSyncData.patternPos = song.curReplayerPattPos;
+		pattSyncData.pattern = song.curReplayerPattNr;
+		pattSyncData.songPos = song.curReplayerSongPos;
+		pattSyncData.speed = song.speed;
+		pattSyncData.tempo = (uint8_t)song.tempo;
+		pattSyncData.globalVol = (uint8_t)song.globVol;
+		pattSyncData.timestamp = audio.tickTime64;
+		pattQueuePush(pattSyncData);
+	}
+
+	// push channel variables to sync queue
+
+	c = chSyncData.channels;
+	s = stm;
+
+	for (int32_t i = 0; i < song.antChn; i++, c++, s++)
+	{
+		c->finalPeriod = s->finalPeriod;
+		c->fineTune = s->fineTune;
+		c->relTonNr = s->relTonNr;
+		c->instrNr = s->instrNr;
+		c->sampleNr = s->sampleNr;
+		c->envSustainActive = s->envSustainActive;
+		c->status = s->tmpStatus;
+		c->finalVol = s->finalVol;
+		c->smpStartPos = s->smpStartPos;
+	}
+
+	chSyncData.timestamp = audio.tickTime64;
+	chQueuePush(chSyncData);
+
+	audio.tickTime64 += tickTimeLen;
+	audio.tickTime64Frac += tickTimeLenFrac;
+	if (audio.tickTime64Frac > 0xFFFFFFFF)
+	{
+		audio.tickTime64Frac &= 0xFFFFFFFF;
+		audio.tickTime64++;
+	}
+}
+
+static void SDLCALL audioCallback(void *userdata, Uint8 *stream, int len)
+{
+	int32_t a, b;
+
 	assert(len < 65536); // limitation in mixer
 	assert(pmpCountDiv > 0);
 
@@ -899,7 +940,7 @@
 	{
 		if (pmpLeft == 0)
 		{
-			// replayer tick
+			// new replayer tick
 
 			replayerBusy = true;
 
@@ -908,61 +949,10 @@
 
 			mainPlayer();
 			mix_UpdateChannelVolPanFrq();
+			fillVisualsSyncBuffer();
 
-			// AUDIO/VIDEO SYNC
-
-			if (audio.resetSyncTickTimeFlag)
-			{
-				audio.resetSyncTickTimeFlag = false;
-
-				audio.tickTime64 = SDL_GetPerformanceCounter() + audio.audLatencyPerfValInt;
-				audio.tickTime64Frac = audio.audLatencyPerfValFrac;
-			}
-
-			if (songPlaying)
-			{
-				// push pattern variables to sync queue
-				pattSyncData.timer = song.curReplayerTimer;
-				pattSyncData.patternPos = song.curReplayerPattPos;
-				pattSyncData.pattern = song.curReplayerPattNr;
-				pattSyncData.songPos = song.curReplayerSongPos;
-				pattSyncData.speed = song.speed;
-				pattSyncData.tempo = (uint8_t)song.tempo;
-				pattSyncData.globalVol = (uint8_t)song.globVol;
-				pattSyncData.timestamp = audio.tickTime64;
-				pattQueuePush(pattSyncData);
-			}
-
-			// push channel variables to sync queue
-
-			c = chSyncData.channels;
-			s = stm;
-
-			for (int32_t i = 0; i < song.antChn; i++, c++, s++)
-			{
-				c->finalPeriod = s->finalPeriod;
-				c->fineTune = s->fineTune;
-				c->relTonNr = s->relTonNr;
-				c->instrNr = s->instrNr;
-				c->sampleNr = s->sampleNr;
-				c->envSustainActive = s->envSustainActive;
-				c->status = s->tmpStatus;
-				c->finalVol = s->finalVol;
-				c->smpStartPos = s->smpStartPos;
-			}
-
-			chSyncData.timestamp = audio.tickTime64;
-			chQueuePush(chSyncData);
-
-			audio.tickTime64 += tickTimeLen;
-			audio.tickTime64Frac += tickTimeLenFrac;
-			if (audio.tickTime64Frac > 0xFFFFFFFF)
-			{
-				audio.tickTime64Frac &= 0xFFFFFFFF;
-				audio.tickTime64++;
-			}
-
 			pmpLeft = audio.speedVal;
+
 			replayerBusy = false;
 		}
 
@@ -976,6 +966,8 @@
 		a -= b;
 		pmpLeft -= b;
 	}
+
+	(void)userdata;
 }
 
 static bool setupAudioBuffers(void)
@@ -1054,15 +1046,14 @@
 		unlockMixerCallback();
 }
 
-static void calcAudioLatencyVars(uint16_t haveSamples, int32_t haveFreq)
+static void calcAudioLatencyVars(int32_t audioBufferSize, int32_t audioFreq)
 {
-	double dHaveFreq, dAudioLatencySecs, dInt, dFrac;
+	double dInt, dFrac;
 
-	dHaveFreq = haveFreq;
-	if (dHaveFreq == 0.0)
-		return; // panic!
+	if (audioFreq == 0)
+		return;
 
-	dAudioLatencySecs = haveSamples / dHaveFreq;
+	const double dAudioLatencySecs = audioBufferSize / (double)audioFreq;
 
 	dFrac = modf(dAudioLatencySecs * editor.dPerfFreq, &dInt);
 
@@ -1134,7 +1125,7 @@
 	want.format = (config.specialFlags & BITDEPTH_32) ? AUDIO_F32 : AUDIO_S16;
 	want.channels = 2;
 	// -------------------------------------------------------------------------------
-	want.callback = mixCallback;
+	want.callback = audioCallback;
 	want.samples  = configAudioBufSize;
 
 	audio.dev = SDL_OpenAudioDevice(audio.currOutputDevice, 0, &want, &have, SDL_AUDIO_ALLOW_ANY_CHANGE); // prevent SDL2 from resampling
--- a/src/ft2_audio.h
+++ b/src/ft2_audio.h
@@ -11,7 +11,7 @@
 	FREQ_TABLE_AMIGA = 1,
 };
 
-/*  Use 16 on non-x86_64 platforms so that we can avoid a
+/* Use 16 on non-x86_64 platforms so that we can avoid a
 ** 64-bit division in the outside mixer loop. x86_64 users
 ** are lucky and will get double the fractional delta precision.
 ** This is beneficial in 96kHz/192kHz mode, where deltas are
@@ -50,10 +50,10 @@
 	bool linearFreqTable, rescanAudioDevicesSupported;
 	int32_t inputDeviceNum, outputDeviceNum, lastWorkingAudioFreq, lastWorkingAudioBits;
 	int32_t quickVolSizeVal, *mixBufferL, *mixBufferR, *mixBufferLUnaligned, *mixBufferRUnaligned;
-	int32_t rampQuickVolMul, rampSpeedValMul;
+	int32_t rampQuickVolMul, rampSpeedValMul, speedValTab[MAX_BPM+1], rampSpeedValMulTab[MAX_BPM+1];
 	uint32_t freq;
 	uint32_t audLatencyPerfValInt, audLatencyPerfValFrac, speedVal, musicTimeSpeedVal;
-	uint64_t tickTime64, tickTime64Frac;
+	uint64_t tickTime64, tickTime64Frac, tickTimeLengthTab[MAX_BPM+1];
 	double dAudioLatencyMs, dSpeedValMul, dPianoDeltaMul;
 	SDL_AudioDeviceID dev;
 	uint32_t wantFreq, haveFreq, wantSamples, haveSamples, wantChannels, haveChannels;
@@ -111,7 +111,7 @@
 extern chSync_t chSync;
 extern pattSync_t pattSync;
 
-extern volatile bool pattQueueReading, pattQueueClearing, chQueueReading, chQueueClearing;
+extern volatile bool pattQueueClearing, chQueueClearing;
 
 #if !defined __amd64__ && !defined _WIN64
 void resetCachedMixerVars(void);
--- a/src/ft2_inst_ed.c
+++ b/src/ft2_inst_ed.c
@@ -22,6 +22,7 @@
 #include "ft2_tables.h"
 #include "ft2_bmp.h"
 #include "ft2_structs.h"
+#include "ft2_bmp.h"
 
 #ifdef _MSC_VER
 #pragma pack(push)
@@ -2008,12 +2009,87 @@
 	}
 }
 
+static void textOutTiny(int32_t xPos, int32_t yPos, char *str, uint32_t color)
+{
+	uint32_t *dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];
+
+	while (*str != '\0')
+	{
+		const char chr = *str++;
+		if (chr < '0' || chr > '9')
+		{
+			dstPtr += FONT3_CHAR_W;
+			continue;
+		}
+
+		const uint8_t *srcPtr = &bmp.font3[(chr - '0') * FONT3_CHAR_W];
+		for (int32_t y = 0; y < FONT3_CHAR_H; y++)
+		{
+			for (int32_t x = 0; x < FONT3_CHAR_W; x++)
+			{
+				if (srcPtr[x])
+					dstPtr[x] = color;
+			}
+
+			srcPtr += FONT3_WIDTH;
+			dstPtr += SCREEN_W;
+		}
+
+		dstPtr -= (SCREEN_W * FONT3_CHAR_H) - FONT3_CHAR_W;
+	}
+}
+
+static void drawVolEnvCoords(int16_t tick, int16_t val)
+{
+	char str[8];
+
+	tick = CLAMP(tick, 0, 324);
+	val = CLAMP(val, 0, 64);
+	
+	sprintf(str, "%03d %02d", tick, val);
+
+	textOutTiny(312, 190, str, video.palette[PAL_BCKGRND]);
+	textOutTiny(313, 189, str, video.palette[PAL_BCKGRND]);
+	textOutTiny(314, 190, str, video.palette[PAL_BCKGRND]);
+	textOutTiny(313, 191, str, video.palette[PAL_BCKGRND]);
+	textOutTiny(313, 190, str, video.palette[PAL_FORGRND]);
+
+}
+
+static void drawPanEnvCoords(int16_t tick, int16_t val)
+{
+	char str[8];
+
+	tick = CLAMP(tick, 0, 324);
+	val = CLAMP(val, 0, 63);
+
+	sprintf(str, "%03d %02d", tick, val);
+
+	textOutTiny(312, 276, str, video.palette[PAL_BCKGRND]);
+	textOutTiny(313, 275, str, video.palette[PAL_BCKGRND]);
+	textOutTiny(314, 276, str, video.palette[PAL_BCKGRND]);
+	textOutTiny(313, 277, str, video.palette[PAL_BCKGRND]);
+	textOutTiny(313, 276, str, video.palette[PAL_FORGRND]);
+}
+
 void handleInstEditorRedrawing(void)
 {
+	instrTyp *ins = instr[editor.curInstr];
+
+	int16_t tick, val;
 	if (updateVolEnv)
 	{
 		updateVolEnv = false;
 		writeEnvelope(0);
+
+		tick = val = 0;
+		if (ins != NULL)
+		{
+			tick = ins->envVP[editor.currVolEnvPoint][0];
+			val = ins->envVP[editor.currVolEnvPoint][1];
+		}
+
+		drawVolEnvCoords(tick, val);
 	}
 
 	if (updatePanEnv)
@@ -2020,6 +2096,15 @@
 	{
 		updatePanEnv = false;
 		writeEnvelope(1);
+
+		tick = val = 0;
+		if (ins != NULL)
+		{
+			tick = ins->envPP[editor.currPanEnvPoint][0];
+			val = ins->envPP[editor.currPanEnvPoint][1];
+		}
+
+		drawPanEnvCoords(tick, val);
 	}
 }
 
--- a/src/ft2_intrp_table.c
+++ b/src/ft2_intrp_table.c
@@ -2061,138 +2061,266 @@
 
 #else
 
-// for non-x86_64 CPUs: 15-bit precision, 512 phases
+// for non-x86_64 CPUs: 15-bit precision, 1024 phases
 
 const int16_t cubicSplineTable[CUBIC_WIDTH * CUBIC_PHASES] =
 {
-	    0, 32767,     0,     0,   -32, 32767,    32,     0,   -64, 32767,    65,     0,   -95, 32766,    98,    -1,
-	 -126, 32763,   132,    -1,  -157, 32761,   166,    -2,  -188, 32757,   201,    -2,  -218, 32753,   236,    -3,
-	 -248, 32748,   272,    -4,  -278, 32743,   308,    -5,  -308, 32737,   345,    -6,  -337, 32730,   382,    -7,
-	 -366, 32724,   419,    -9,  -395, 32716,   457,   -10,  -424, 32708,   496,   -12,  -452, 32699,   535,   -14,
-	 -481, 32690,   575,   -16,  -508, 32679,   614,   -17,  -536, 32669,   655,   -20,  -564, 32658,   696,   -22,
-	 -591, 32646,   737,   -24,  -618, 32633,   779,   -26,  -645, 32621,   821,   -29,  -671, 32607,   864,   -32,
-	 -698, 32593,   907,   -34,  -724, 32578,   951,   -37,  -750, 32563,   995,   -40,  -775, 32547,  1039,   -43,
-	 -801, 32531,  1084,   -46,  -826, 32515,  1129,   -50,  -851, 32497,  1175,   -53,  -876, 32479,  1221,   -56,
-	 -900, 32460,  1268,   -60,  -924, 32441,  1315,   -64,  -948, 32420,  1363,   -67,  -972, 32400,  1411,   -71,
-	 -996, 32380,  1459,   -75, -1019, 32358,  1508,   -79, -1042, 32337,  1557,   -84, -1065, 32314,  1607,   -88,
-	-1088, 32291,  1657,   -92, -1110, 32268,  1707,   -97, -1133, 32244,  1758,  -101, -1155, 32220,  1809,  -106,
-	-1176, 32194,  1861,  -111, -1198, 32168,  1913,  -115, -1219, 32142,  1965,  -120, -1241, 32116,  2018,  -125,
-	-1262, 32089,  2072,  -131, -1282, 32061,  2125,  -136, -1303, 32033,  2179,  -141, -1323, 32003,  2234,  -146,
-	-1343, 31974,  2289,  -152, -1363, 31944,  2344,  -157, -1383, 31915,  2399,  -163, -1402, 31884,  2455,  -169,
-	-1421, 31852,  2512,  -175, -1440, 31820,  2568,  -180, -1459, 31787,  2626,  -186, -1478, 31755,  2683,  -192,
-	-1496, 31722,  2741,  -199, -1515, 31689,  2799,  -205, -1533, 31654,  2858,  -211, -1550, 31619,  2917,  -218,
-	-1568, 31584,  2976,  -224, -1585, 31548,  3036,  -231, -1603, 31512,  3096,  -237, -1620, 31476,  3156,  -244,
-	-1636, 31438,  3217,  -251, -1653, 31400,  3278,  -257, -1669, 31362,  3339,  -264, -1686, 31324,  3401,  -271,
-	-1702, 31285,  3463,  -278, -1717, 31245,  3526,  -286, -1733, 31205,  3589,  -293, -1748, 31164,  3652,  -300,
-	-1764, 31124,  3715,  -307, -1779, 31083,  3779,  -315, -1793, 31040,  3843,  -322, -1808, 30998,  3908,  -330,
-	-1823, 30956,  3973,  -338, -1837, 30912,  4038,  -345, -1851, 30869,  4103,  -353, -1865, 30825,  4169,  -361,
-	-1878, 30780,  4235,  -369, -1892, 30736,  4301,  -377, -1905, 30690,  4368,  -385, -1918, 30644,  4435,  -393,
-	-1931, 30598,  4502,  -401, -1944, 30551,  4570,  -409, -1956, 30503,  4638,  -417, -1969, 30457,  4706,  -426,
-	-1981, 30408,  4775,  -434, -1993, 30359,  4844,  -442, -2005, 30311,  4913,  -451, -2017, 30262,  4982,  -459,
-	-2028, 30212,  5052,  -468, -2039, 30162,  5122,  -477, -2050, 30111,  5192,  -485, -2061, 30060,  5263,  -494,
-	-2072, 30009,  5334,  -503, -2083, 29958,  5405,  -512, -2093, 29906,  5476,  -521, -2103, 29853,  5548,  -530,
-	-2113, 29800,  5620,  -539, -2123, 29747,  5692,  -548, -2133, 29693,  5765,  -557, -2142, 29638,  5838,  -566,
-	-2152, 29584,  5911,  -575, -2161, 29529,  5984,  -584, -2170, 29474,  6058,  -594, -2179, 29419,  6131,  -603,
-	-2188, 29363,  6206,  -613, -2196, 29306,  6280,  -622, -2204, 29249,  6354,  -631, -2213, 29193,  6429,  -641,
-	-2221, 29135,  6504,  -650, -2228, 29076,  6580,  -660, -2236, 29019,  6655,  -670, -2244, 28960,  6731,  -679,
-	-2251, 28901,  6807,  -689, -2258, 28842,  6883,  -699, -2265, 28782,  6960,  -709, -2272, 28721,  7037,  -718,
-	-2279, 28661,  7114,  -728, -2285, 28600,  7191,  -738, -2292, 28540,  7268,  -748, -2298, 28478,  7346,  -758,
-	-2304, 28416,  7424,  -768, -2310, 28354,  7502,  -778, -2316, 28292,  7580,  -788, -2321, 28228,  7659,  -798,
-	-2327, 28165,  7738,  -808, -2332, 28101,  7817,  -818, -2337, 28038,  7896,  -829, -2342, 27974,  7975,  -839,
-	-2347, 27909,  8055,  -849, -2352, 27844,  8135,  -859, -2356, 27778,  8215,  -869, -2361, 27714,  8295,  -880,
-	-2365, 27648,  8375,  -890, -2369, 27581,  8456,  -900, -2373, 27516,  8536,  -911, -2377, 27449,  8617,  -921,
-	-2381, 27382,  8699,  -932, -2384, 27314,  8780,  -942, -2387, 27246,  8861,  -952, -2391, 27179,  8943,  -963,
-	-2394, 27110,  9025,  -973, -2397, 27042,  9107,  -984, -2399, 26972,  9189,  -994, -2402, 26904,  9271, -1005,
-	-2405, 26834,  9354, -1015, -2407, 26764,  9437, -1026, -2409, 26693,  9520, -1036, -2411, 26623,  9603, -1047,
-	-2413, 26553,  9686, -1058, -2415, 26482,  9769, -1068, -2417, 26411,  9853, -1079, -2419, 26340,  9936, -1089,
-	-2420, 26268, 10020, -1100, -2421, 26196, 10104, -1111, -2422, 26123, 10188, -1121, -2424, 26052, 10272, -1132,
-	-2424, 25978, 10357, -1143, -2425, 25905, 10441, -1153, -2426, 25832, 10526, -1164, -2426, 25758, 10611, -1175,
-	-2427, 25684, 10696, -1185, -2427, 25610, 10781, -1196, -2427, 25536, 10866, -1207, -2427, 25461, 10951, -1217,
-	-2427, 25386, 11037, -1228, -2427, 25312, 11122, -1239, -2427, 25236, 11208, -1249, -2426, 25160, 11294, -1260,
-	-2426, 25085, 11380, -1271, -2425, 25008, 11466, -1281, -2424, 24932, 11552, -1292, -2423, 24855, 11638, -1302,
-	-2422, 24779, 11724, -1313, -2421, 24702, 11811, -1324, -2419, 24624, 11897, -1334, -2418, 24547, 11984, -1345,
-	-2416, 24469, 12071, -1356, -2415, 24391, 12158, -1366, -2413, 24314, 12244, -1377, -2411, 24234, 12332, -1387,
-	-2409, 24156, 12419, -1398, -2407, 24077, 12506, -1408, -2405, 23999, 12593, -1419, -2402, 23918, 12681, -1429,
-	-2400, 23840, 12768, -1440, -2397, 23759, 12856, -1450, -2395, 23681, 12943, -1461, -2392, 23600, 13031, -1471,
-	-2389, 23520, 13119, -1482, -2386, 23440, 13206, -1492, -2383, 23360, 13294, -1503, -2380, 23279, 13382, -1513,
-	-2377, 23198, 13470, -1523, -2373, 23117, 13558, -1534, -2370, 23035, 13647, -1544, -2366, 22953, 13735, -1554,
-	-2362, 22872, 13823, -1565, -2359, 22791, 13911, -1575, -2355, 22708, 14000, -1585, -2351, 22626, 14088, -1595,
-	-2347, 22544, 14177, -1606, -2342, 22461, 14265, -1616, -2338, 22378, 14354, -1626, -2334, 22296, 14442, -1636,
-	-2329, 22212, 14531, -1646, -2325, 22130, 14619, -1656, -2320, 22046, 14708, -1666, -2315, 21962, 14797, -1676,
-	-2310, 21879, 14885, -1686, -2305, 21795, 14974, -1696, -2300, 21711, 15063, -1706, -2295, 21626, 15152, -1715,
-	-2290, 21542, 15241, -1725, -2284, 21458, 15329, -1735, -2279, 21374, 15418, -1745, -2274, 21289, 15507, -1754,
-	-2268, 21204, 15596, -1764, -2262, 21119, 15685, -1774, -2257, 21034, 15774, -1783, -2251, 20949, 15863, -1793,
-	-2245, 20863, 15952, -1802, -2239, 20779, 16040, -1812, -2233, 20693, 16129, -1821, -2227, 20607, 16218, -1830,
-	-2220, 20521, 16307, -1840, -2214, 20435, 16396, -1849, -2208, 20349, 16485, -1858, -2201, 20262, 16574, -1867,
-	-2195, 20177, 16662, -1876, -2188, 20091, 16751, -1886, -2181, 20004, 16840, -1895, -2174, 19917, 16929, -1904,
-	-2168, 19831, 17018, -1913, -2161, 19744, 17106, -1921, -2154, 19657, 17195, -1930, -2146, 19569, 17284, -1939,
-	-2139, 19483, 17372, -1948, -2132, 19395, 17461, -1956, -2125, 19309, 17549, -1965, -2117, 19221, 17638, -1974,
-	-2110, 19134, 17726, -1982, -2102, 19046, 17815, -1991, -2095, 18959, 17903, -1999, -2087, 18871, 17991, -2007,
-	-2079, 18783, 18080, -2016, -2072, 18696, 18168, -2024, -2064, 18608, 18256, -2032, -2056, 18520, 18344, -2040,
-	-2048, 18432, 18432, -2048, -2040, 18344, 18520, -2056, -2032, 18256, 18608, -2064, -2024, 18168, 18696, -2072,
-	-2016, 18080, 18783, -2079, -2007, 17991, 18871, -2087, -1999, 17903, 18959, -2095, -1991, 17815, 19046, -2102,
-	-1982, 17726, 19134, -2110, -1974, 17638, 19221, -2117, -1965, 17549, 19309, -2125, -1956, 17461, 19395, -2132,
-	-1948, 17372, 19483, -2139, -1939, 17284, 19569, -2146, -1930, 17195, 19657, -2154, -1921, 17106, 19744, -2161,
-	-1913, 17018, 19831, -2168, -1904, 16929, 19917, -2174, -1895, 16840, 20004, -2181, -1886, 16751, 20091, -2188,
-	-1876, 16662, 20177, -2195, -1867, 16574, 20262, -2201, -1858, 16485, 20349, -2208, -1849, 16396, 20435, -2214,
-	-1840, 16307, 20521, -2220, -1830, 16218, 20607, -2227, -1821, 16129, 20693, -2233, -1812, 16040, 20779, -2239,
-	-1802, 15952, 20863, -2245, -1793, 15863, 20949, -2251, -1783, 15774, 21034, -2257, -1774, 15685, 21119, -2262,
-	-1764, 15596, 21204, -2268, -1754, 15507, 21289, -2274, -1745, 15418, 21374, -2279, -1735, 15329, 21458, -2284,
-	-1725, 15241, 21542, -2290, -1715, 15152, 21626, -2295, -1706, 15063, 21711, -2300, -1696, 14974, 21795, -2305,
-	-1686, 14885, 21879, -2310, -1676, 14797, 21962, -2315, -1666, 14708, 22046, -2320, -1656, 14619, 22130, -2325,
-	-1646, 14531, 22212, -2329, -1636, 14442, 22296, -2334, -1626, 14354, 22378, -2338, -1616, 14265, 22461, -2342,
-	-1606, 14177, 22544, -2347, -1595, 14088, 22626, -2351, -1585, 14000, 22708, -2355, -1575, 13911, 22791, -2359,
-	-1565, 13823, 22872, -2362, -1554, 13735, 22953, -2366, -1544, 13647, 23035, -2370, -1534, 13558, 23117, -2373,
-	-1523, 13470, 23198, -2377, -1513, 13382, 23279, -2380, -1503, 13294, 23360, -2383, -1492, 13206, 23440, -2386,
-	-1482, 13119, 23520, -2389, -1471, 13031, 23600, -2392, -1461, 12943, 23681, -2395, -1450, 12856, 23759, -2397,
-	-1440, 12768, 23840, -2400, -1429, 12681, 23918, -2402, -1419, 12593, 23999, -2405, -1408, 12506, 24077, -2407,
-	-1398, 12419, 24156, -2409, -1387, 12332, 24234, -2411, -1377, 12244, 24314, -2413, -1366, 12158, 24391, -2415,
-	-1356, 12071, 24469, -2416, -1345, 11984, 24547, -2418, -1334, 11897, 24624, -2419, -1324, 11811, 24702, -2421,
-	-1313, 11724, 24779, -2422, -1302, 11638, 24855, -2423, -1292, 11552, 24932, -2424, -1281, 11466, 25008, -2425,
-	-1271, 11380, 25085, -2426, -1260, 11294, 25160, -2426, -1249, 11208, 25236, -2427, -1239, 11122, 25312, -2427,
-	-1228, 11037, 25386, -2427, -1217, 10951, 25461, -2427, -1207, 10866, 25536, -2427, -1196, 10781, 25610, -2427,
-	-1185, 10696, 25684, -2427, -1175, 10611, 25758, -2426, -1164, 10526, 25832, -2426, -1153, 10441, 25905, -2425,
-	-1143, 10357, 25978, -2424, -1132, 10272, 26052, -2424, -1121, 10188, 26123, -2422, -1111, 10104, 26196, -2421,
-	-1100, 10020, 26268, -2420, -1089,  9936, 26340, -2419, -1079,  9853, 26411, -2417, -1068,  9769, 26482, -2415,
-	-1058,  9686, 26553, -2413, -1047,  9603, 26623, -2411, -1036,  9520, 26693, -2409, -1026,  9437, 26764, -2407,
-	-1015,  9354, 26834, -2405, -1005,  9271, 26904, -2402,  -994,  9189, 26972, -2399,  -984,  9107, 27042, -2397,
-	 -973,  9025, 27110, -2394,  -963,  8943, 27179, -2391,  -952,  8861, 27246, -2387,  -942,  8780, 27314, -2384,
-	 -932,  8699, 27382, -2381,  -921,  8617, 27449, -2377,  -911,  8536, 27516, -2373,  -900,  8456, 27581, -2369,
-	 -890,  8375, 27648, -2365,  -880,  8295, 27714, -2361,  -869,  8215, 27778, -2356,  -859,  8135, 27844, -2352,
-	 -849,  8055, 27909, -2347,  -839,  7975, 27974, -2342,  -829,  7896, 28038, -2337,  -818,  7817, 28101, -2332,
-	 -808,  7738, 28165, -2327,  -798,  7659, 28228, -2321,  -788,  7580, 28292, -2316,  -778,  7502, 28354, -2310,
-	 -768,  7424, 28416, -2304,  -758,  7346, 28478, -2298,  -748,  7268, 28540, -2292,  -738,  7191, 28600, -2285,
-	 -728,  7114, 28661, -2279,  -718,  7037, 28721, -2272,  -709,  6960, 28782, -2265,  -699,  6883, 28842, -2258,
-	 -689,  6807, 28901, -2251,  -679,  6731, 28960, -2244,  -670,  6655, 29019, -2236,  -660,  6580, 29076, -2228,
-	 -650,  6504, 29135, -2221,  -641,  6429, 29193, -2213,  -631,  6354, 29249, -2204,  -622,  6280, 29306, -2196,
-	 -613,  6206, 29363, -2188,  -603,  6131, 29419, -2179,  -594,  6058, 29474, -2170,  -584,  5984, 29529, -2161,
-	 -575,  5911, 29584, -2152,  -566,  5838, 29638, -2142,  -557,  5765, 29693, -2133,  -548,  5692, 29747, -2123,
-	 -539,  5620, 29800, -2113,  -530,  5548, 29853, -2103,  -521,  5476, 29906, -2093,  -512,  5405, 29958, -2083,
-	 -503,  5334, 30009, -2072,  -494,  5263, 30060, -2061,  -485,  5192, 30111, -2050,  -477,  5122, 30162, -2039,
-	 -468,  5052, 30212, -2028,  -459,  4982, 30262, -2017,  -451,  4913, 30311, -2005,  -442,  4844, 30359, -1993,
-	 -434,  4775, 30408, -1981,  -426,  4706, 30457, -1969,  -417,  4638, 30503, -1956,  -409,  4570, 30551, -1944,
-	 -401,  4502, 30598, -1931,  -393,  4435, 30644, -1918,  -385,  4368, 30690, -1905,  -377,  4301, 30736, -1892,
-	 -369,  4235, 30780, -1878,  -361,  4169, 30825, -1865,  -353,  4103, 30869, -1851,  -345,  4038, 30912, -1837,
-	 -338,  3973, 30956, -1823,  -330,  3908, 30998, -1808,  -322,  3843, 31040, -1793,  -315,  3779, 31083, -1779,
-	 -307,  3715, 31124, -1764,  -300,  3652, 31164, -1748,  -293,  3589, 31205, -1733,  -286,  3526, 31245, -1717,
-	 -278,  3463, 31285, -1702,  -271,  3401, 31324, -1686,  -264,  3339, 31362, -1669,  -257,  3278, 31400, -1653,
-	 -251,  3217, 31438, -1636,  -244,  3156, 31476, -1620,  -237,  3096, 31512, -1603,  -231,  3036, 31548, -1585,
-	 -224,  2976, 31584, -1568,  -218,  2917, 31619, -1550,  -211,  2858, 31654, -1533,  -205,  2799, 31689, -1515,
-	 -199,  2741, 31722, -1496,  -192,  2683, 31755, -1478,  -186,  2626, 31787, -1459,  -180,  2568, 31820, -1440,
-	 -175,  2512, 31852, -1421,  -169,  2455, 31884, -1402,  -163,  2399, 31915, -1383,  -157,  2344, 31944, -1363,
-	 -152,  2289, 31974, -1343,  -146,  2234, 32003, -1323,  -141,  2179, 32033, -1303,  -136,  2125, 32061, -1282,
-	 -131,  2072, 32089, -1262,  -125,  2018, 32116, -1241,  -120,  1965, 32142, -1219,  -115,  1913, 32168, -1198,
-	 -111,  1861, 32194, -1176,  -106,  1809, 32220, -1155,  -101,  1758, 32244, -1133,   -97,  1707, 32268, -1110,
-	  -92,  1657, 32291, -1088,   -88,  1607, 32314, -1065,   -84,  1557, 32337, -1042,   -79,  1508, 32358, -1019,
-	  -75,  1459, 32380,  -996,   -71,  1411, 32400,  -972,   -67,  1363, 32420,  -948,   -64,  1315, 32441,  -924,
-	  -60,  1268, 32460,  -900,   -56,  1221, 32479,  -876,   -53,  1175, 32497,  -851,   -50,  1129, 32515,  -826,
-	  -46,  1084, 32531,  -801,   -43,  1039, 32547,  -775,   -40,   995, 32563,  -750,   -37,   951, 32578,  -724,
-	  -34,   907, 32593,  -698,   -32,   864, 32607,  -671,   -29,   821, 32621,  -645,   -26,   779, 32633,  -618,
-	  -24,   737, 32646,  -591,   -22,   696, 32658,  -564,   -20,   655, 32669,  -536,   -17,   614, 32679,  -508,
-	  -16,   575, 32690,  -481,   -14,   535, 32699,  -452,   -12,   496, 32708,  -424,   -10,   457, 32716,  -395,
-	   -9,   419, 32724,  -366,    -7,   382, 32730,  -337,    -6,   345, 32737,  -308,    -5,   308, 32743,  -278,
-	   -4,   272, 32748,  -248,    -3,   236, 32753,  -218,    -2,   201, 32757,  -188,    -2,   166, 32761,  -157,
-	   -1,   132, 32763,  -126,    -1,    98, 32766,   -95,     0,    65, 32767,   -64,     0,    32, 32767,   -32
+	    0, 32767,     0,     0,   -16, 32767,    16,     0,   -32, 32767,    32,     0,   -48, 32767,    49,     0,
+	  -64, 32767,    65,     0,   -79, 32765,    82,     0,   -95, 32766,    98,    -1,  -110, 32764,   115,    -1,
+	 -126, 32763,   132,    -1,  -141, 32761,   149,    -1,  -157, 32761,   166,    -2,  -172, 32758,   184,    -2,
+	 -188, 32757,   201,    -2,  -203, 32756,   218,    -3,  -218, 32753,   236,    -3,  -233, 32750,   254,    -3,
+	 -248, 32748,   272,    -4,  -263, 32745,   290,    -4,  -278, 32743,   308,    -5,  -293, 32741,   326,    -6,
+	 -308, 32737,   345,    -6,  -322, 32734,   363,    -7,  -337, 32730,   382,    -7,  -352, 32727,   401,    -8,
+	 -366, 32724,   419,    -9,  -381, 32721,   438,   -10,  -395, 32716,   457,   -10,  -410, 32712,   477,   -11,
+	 -424, 32708,   496,   -12,  -438, 32704,   515,   -13,  -452, 32699,   535,   -14,  -466, 32694,   555,   -15,
+	 -481, 32690,   575,   -16,  -495, 32685,   594,   -16,  -508, 32679,   614,   -17,  -522, 32673,   635,   -18,
+	 -536, 32669,   655,   -20,  -550, 32664,   675,   -21,  -564, 32658,   696,   -22,  -577, 32652,   716,   -23,
+	 -591, 32646,   737,   -24,  -605, 32640,   758,   -25,  -618, 32633,   779,   -26,  -631, 32627,   800,   -28,
+	 -645, 32621,   821,   -29,  -658, 32614,   842,   -30,  -671, 32607,   864,   -32,  -685, 32601,   885,   -33,
+	 -698, 32593,   907,   -34,  -711, 32586,   929,   -36,  -724, 32578,   951,   -37,  -737, 32572,   972,   -39,
+	 -750, 32563,   995,   -40,  -762, 32555,  1017,   -42,  -775, 32547,  1039,   -43,  -788, 32540,  1061,   -45,
+	 -801, 32531,  1084,   -46,  -813, 32522,  1107,   -48,  -826, 32515,  1129,   -50,  -838, 32505,  1152,   -51,
+	 -851, 32497,  1175,   -53,  -863, 32488,  1198,   -55,  -876, 32479,  1221,   -56,  -888, 32469,  1245,   -58,
+	 -900, 32460,  1268,   -60,  -912, 32451,  1291,   -62,  -924, 32441,  1315,   -64,  -936, 32431,  1339,   -66,
+	 -948, 32420,  1363,   -67,  -960, 32410,  1387,   -69,  -972, 32400,  1411,   -71,  -984, 32390,  1435,   -73,
+	 -996, 32380,  1459,   -75, -1007, 32369,  1483,   -77, -1019, 32358,  1508,   -79, -1031, 32348,  1532,   -81,
+	-1042, 32337,  1557,   -84, -1054, 32326,  1582,   -86, -1065, 32314,  1607,   -88, -1076, 32303,  1631,   -90,
+	-1088, 32291,  1657,   -92, -1099, 32279,  1682,   -94, -1110, 32268,  1707,   -97, -1121, 32256,  1732,   -99,
+	-1133, 32244,  1758,  -101, -1144, 32233,  1783,  -104, -1155, 32220,  1809,  -106, -1166, 32207,  1835,  -108,
+	-1176, 32194,  1861,  -111, -1187, 32181,  1887,  -113, -1198, 32168,  1913,  -115, -1209, 32156,  1939,  -118,
+	-1219, 32142,  1965,  -120, -1230, 32129,  1992,  -123, -1241, 32116,  2018,  -125, -1251, 32102,  2045,  -128,
+	-1262, 32089,  2072,  -131, -1272, 32075,  2098,  -133, -1282, 32061,  2125,  -136, -1293, 32047,  2152,  -138,
+	-1303, 32033,  2179,  -141, -1313, 32019,  2206,  -144, -1323, 32003,  2234,  -146, -1333, 31989,  2261,  -149,
+	-1343, 31974,  2289,  -152, -1353, 31960,  2316,  -155, -1363, 31944,  2344,  -157, -1373, 31930,  2371,  -160,
+	-1383, 31915,  2399,  -163, -1392, 31899,  2427,  -166, -1402, 31884,  2455,  -169, -1412, 31869,  2483,  -172,
+	-1421, 31852,  2512,  -175, -1431, 31836,  2540,  -177, -1440, 31820,  2568,  -180, -1450, 31804,  2597,  -183,
+	-1459, 31787,  2626,  -186, -1469, 31772,  2654,  -189, -1478, 31755,  2683,  -192, -1487, 31739,  2712,  -196,
+	-1496, 31722,  2741,  -199, -1506, 31706,  2770,  -202, -1515, 31689,  2799,  -205, -1524, 31672,  2828,  -208,
+	-1533, 31654,  2858,  -211, -1542, 31637,  2887,  -214, -1550, 31619,  2917,  -218, -1559, 31602,  2946,  -221,
+	-1568, 31584,  2976,  -224, -1577, 31566,  3006,  -227, -1585, 31548,  3036,  -231, -1594, 31530,  3066,  -234,
+	-1603, 31512,  3096,  -237, -1611, 31493,  3126,  -240, -1620, 31476,  3156,  -244, -1628, 31457,  3186,  -247,
+	-1636, 31438,  3217,  -251, -1645, 31420,  3247,  -254, -1653, 31400,  3278,  -257, -1661, 31381,  3309,  -261,
+	-1669, 31362,  3339,  -264, -1677, 31343,  3370,  -268, -1686, 31324,  3401,  -271, -1694, 31305,  3432,  -275,
+	-1702, 31285,  3463,  -278, -1709, 31264,  3495,  -282, -1717, 31245,  3526,  -286, -1725, 31225,  3557,  -289,
+	-1733, 31205,  3589,  -293, -1741, 31185,  3620,  -296, -1748, 31164,  3652,  -300, -1756, 31145,  3683,  -304,
+	-1764, 31124,  3715,  -307, -1771, 31103,  3747,  -311, -1779, 31083,  3779,  -315, -1786, 31062,  3811,  -319,
+	-1793, 31040,  3843,  -322, -1801, 31020,  3875,  -326, -1808, 30998,  3908,  -330, -1815, 30977,  3940,  -334,
+	-1823, 30956,  3973,  -338, -1830, 30934,  4005,  -341, -1837, 30912,  4038,  -345, -1844, 30891,  4070,  -349,
+	-1851, 30869,  4103,  -353, -1858, 30847,  4136,  -357, -1865, 30825,  4169,  -361, -1872, 30803,  4202,  -365,
+	-1878, 30780,  4235,  -369, -1885, 30758,  4268,  -373, -1892, 30736,  4301,  -377, -1899, 30713,  4335,  -381,
+	-1905, 30690,  4368,  -385, -1912, 30667,  4402,  -389, -1918, 30644,  4435,  -393, -1925, 30621,  4469,  -397,
+	-1931, 30598,  4502,  -401, -1938, 30575,  4536,  -405, -1944, 30551,  4570,  -409, -1950, 30527,  4604,  -413,
+	-1956, 30503,  4638,  -417, -1963, 30480,  4672,  -421, -1969, 30457,  4706,  -426, -1975, 30432,  4741,  -430,
+	-1981, 30408,  4775,  -434, -1987, 30384,  4809,  -438, -1993, 30359,  4844,  -442, -1999, 30336,  4878,  -447,
+	-2005, 30311,  4913,  -451, -2011, 30286,  4948,  -455, -2017, 30262,  4982,  -459, -2022, 30237,  5017,  -464,
+	-2028, 30212,  5052,  -468, -2034, 30187,  5087,  -472, -2039, 30162,  5122,  -477, -2045, 30137,  5157,  -481,
+	-2050, 30111,  5192,  -485, -2056, 30086,  5228,  -490, -2061, 30060,  5263,  -494, -2067, 30036,  5298,  -499,
+	-2072, 30009,  5334,  -503, -2077, 29983,  5369,  -507, -2083, 29958,  5405,  -512, -2088, 29931,  5441,  -516,
+	-2093, 29906,  5476,  -521, -2098, 29879,  5512,  -525, -2103, 29853,  5548,  -530, -2108, 29826,  5584,  -534,
+	-2113, 29800,  5620,  -539, -2118, 29773,  5656,  -543, -2123, 29747,  5692,  -548, -2128, 29719,  5729,  -552,
+	-2133, 29693,  5765,  -557, -2138, 29666,  5801,  -561, -2142, 29638,  5838,  -566, -2147, 29612,  5874,  -571,
+	-2152, 29584,  5911,  -575, -2156, 29557,  5947,  -580, -2161, 29529,  5984,  -584, -2165, 29501,  6021,  -589,
+	-2170, 29474,  6058,  -594, -2174, 29446,  6094,  -598, -2179, 29419,  6131,  -603, -2183, 29391,  6168,  -608,
+	-2188, 29363,  6206,  -613, -2192, 29334,  6243,  -617, -2196, 29306,  6280,  -622, -2200, 29278,  6317,  -627,
+	-2204, 29249,  6354,  -631, -2208, 29220,  6392,  -636, -2213, 29193,  6429,  -641, -2217, 29164,  6467,  -646,
+	-2221, 29135,  6504,  -650, -2224, 29105,  6542,  -655, -2228, 29076,  6580,  -660, -2232, 29048,  6617,  -665,
+	-2236, 29019,  6655,  -670, -2240, 28990,  6693,  -675, -2244, 28960,  6731,  -679, -2247, 28930,  6769,  -684,
+	-2251, 28901,  6807,  -689, -2255, 28872,  6845,  -694, -2258, 28842,  6883,  -699, -2262, 28812,  6922,  -704,
+	-2265, 28782,  6960,  -709, -2269, 28752,  6998,  -713, -2272, 28721,  7037,  -718, -2275, 28691,  7075,  -723,
+	-2279, 28661,  7114,  -728, -2282, 28631,  7152,  -733, -2285, 28600,  7191,  -738, -2289, 28570,  7230,  -743,
+	-2292, 28540,  7268,  -748, -2295, 28509,  7307,  -753, -2298, 28478,  7346,  -758, -2301, 28447,  7385,  -763,
+	-2304, 28416,  7424,  -768, -2307, 28385,  7463,  -773, -2310, 28354,  7502,  -778, -2313, 28323,  7541,  -783,
+	-2316, 28292,  7580,  -788, -2319, 28260,  7620,  -793, -2321, 28228,  7659,  -798, -2324, 28197,  7698,  -803,
+	-2327, 28165,  7738,  -808, -2329, 28133,  7777,  -813, -2332, 28101,  7817,  -818, -2335, 28070,  7856,  -823,
+	-2337, 28038,  7896,  -829, -2340, 28006,  7936,  -834, -2342, 27974,  7975,  -839, -2345, 27942,  8015,  -844,
+	-2347, 27909,  8055,  -849, -2349, 27876,  8095,  -854, -2352, 27844,  8135,  -859, -2354, 27811,  8175,  -864,
+	-2356, 27778,  8215,  -869, -2359, 27747,  8255,  -875, -2361, 27714,  8295,  -880, -2363, 27681,  8335,  -885,
+	-2365, 27648,  8375,  -890, -2367, 27615,  8415,  -895, -2369, 27581,  8456,  -900, -2371, 27549,  8496,  -906,
+	-2373, 27516,  8536,  -911, -2375, 27482,  8577,  -916, -2377, 27449,  8617,  -921, -2379, 27415,  8658,  -926,
+	-2381, 27382,  8699,  -932, -2382, 27348,  8739,  -937, -2384, 27314,  8780,  -942, -2386, 27280,  8821,  -947,
+	-2387, 27246,  8861,  -952, -2389, 27213,  8902,  -958, -2391, 27179,  8943,  -963, -2392, 27144,  8984,  -968,
+	-2394, 27110,  9025,  -973, -2395, 27076,  9066,  -979, -2397, 27042,  9107,  -984, -2398, 27007,  9148,  -989,
+	-2399, 26972,  9189,  -994, -2401, 26939,  9230, -1000, -2402, 26904,  9271, -1005, -2403, 26868,  9313, -1010,
+	-2405, 26834,  9354, -1015, -2406, 26800,  9395, -1021, -2407, 26764,  9437, -1026, -2408, 26729,  9478, -1031,
+	-2409, 26693,  9520, -1036, -2410, 26659,  9561, -1042, -2411, 26623,  9603, -1047, -2412, 26588,  9644, -1052,
+	-2413, 26553,  9686, -1058, -2414, 26518,  9727, -1063, -2415, 26482,  9769, -1068, -2416, 26446,  9811, -1073,
+	-2417, 26411,  9853, -1079, -2418, 26376,  9894, -1084, -2419, 26340,  9936, -1089, -2419, 26304,  9978, -1095,
+	-2420, 26268, 10020, -1100, -2421, 26232, 10062, -1105, -2421, 26196, 10104, -1111, -2422, 26160, 10146, -1116,
+	-2422, 26123, 10188, -1121, -2423, 26088, 10230, -1127, -2424, 26052, 10272, -1132, -2424, 26015, 10314, -1137,
+	-2424, 25978, 10357, -1143, -2425, 25942, 10399, -1148, -2425, 25905, 10441, -1153, -2426, 25870, 10483, -1159,
+	-2426, 25832, 10526, -1164, -2426, 25795, 10568, -1169, -2426, 25758, 10611, -1175, -2427, 25722, 10653, -1180,
+	-2427, 25684, 10696, -1185, -2427, 25648, 10738, -1191, -2427, 25610, 10781, -1196, -2427, 25573, 10823, -1201,
+	-2427, 25536, 10866, -1207, -2427, 25499, 10908, -1212, -2427, 25461, 10951, -1217, -2427, 25424, 10994, -1223,
+	-2427, 25386, 11037, -1228, -2427, 25349, 11079, -1233, -2427, 25312, 11122, -1239, -2427, 25274, 11165, -1244,
+	-2427, 25236, 11208, -1249, -2426, 25198, 11251, -1255, -2426, 25160, 11294, -1260, -2426, 25122, 11337, -1265,
+	-2426, 25085, 11380, -1271, -2425, 25047, 11422, -1276, -2425, 25008, 11466, -1281, -2424, 24969, 11509, -1286,
+	-2424, 24932, 11552, -1292, -2423, 24893, 11595, -1297, -2423, 24855, 11638, -1302, -2422, 24817, 11681, -1308,
+	-2422, 24779, 11724, -1313, -2421, 24740, 11767, -1318, -2421, 24702, 11811, -1324, -2420, 24663, 11854, -1329,
+	-2419, 24624, 11897, -1334, -2419, 24586, 11941, -1340, -2418, 24547, 11984, -1345, -2417, 24508, 12027, -1350,
+	-2416, 24469, 12071, -1356, -2416, 24431, 12114, -1361, -2415, 24391, 12158, -1366, -2414, 24352, 12201, -1371,
+	-2413, 24314, 12244, -1377, -2412, 24274, 12288, -1382, -2411, 24234, 12332, -1387, -2410, 24196, 12375, -1393,
+	-2409, 24156, 12419, -1398, -2408, 24117, 12462, -1403, -2407, 24077, 12506, -1408, -2406, 24039, 12549, -1414,
+	-2405, 23999, 12593, -1419, -2404, 23959, 12637, -1424, -2402, 23918, 12681, -1429, -2401, 23880, 12724, -1435,
+	-2400, 23840, 12768, -1440, -2399, 23800, 12812, -1445, -2397, 23759, 12856, -1450, -2396, 23721, 12899, -1456,
+	-2395, 23681, 12943, -1461, -2393, 23640, 12987, -1466, -2392, 23600, 13031, -1471, -2391, 23561, 13075, -1477,
+	-2389, 23520, 13119, -1482, -2388, 23480, 13163, -1487, -2386, 23440, 13206, -1492, -2385, 23400, 13250, -1497,
+	-2383, 23360, 13294, -1503, -2381, 23319, 13338, -1508, -2380, 23279, 13382, -1513, -2378, 23238, 13426, -1518,
+	-2377, 23198, 13470, -1523, -2375, 23158, 13514, -1529, -2373, 23117, 13558, -1534, -2371, 23076, 13602, -1539,
+	-2370, 23035, 13647, -1544, -2368, 22994, 13691, -1549, -2366, 22953, 13735, -1554, -2364, 22913, 13779, -1560,
+	-2362, 22872, 13823, -1565, -2360, 22831, 13867, -1570, -2359, 22791, 13911, -1575, -2357, 22750, 13955, -1580,
+	-2355, 22708, 14000, -1585, -2353, 22667, 14044, -1590, -2351, 22626, 14088, -1595, -2349, 22585, 14132, -1600,
+	-2347, 22544, 14177, -1606, -2344, 22502, 14221, -1611, -2342, 22461, 14265, -1616, -2340, 22420, 14309, -1621,
+	-2338, 22378, 14354, -1626, -2336, 22337, 14398, -1631, -2334, 22296, 14442, -1636, -2331, 22254, 14486, -1641,
+	-2329, 22212, 14531, -1646, -2327, 22171, 14575, -1651, -2325, 22130, 14619, -1656, -2322, 22087, 14664, -1661,
+	-2320, 22046, 14708, -1666, -2317, 22004, 14752, -1671, -2315, 21962, 14797, -1676, -2313, 21921, 14841, -1681,
+	-2310, 21879, 14885, -1686, -2308, 21837, 14930, -1691, -2305, 21795, 14974, -1696, -2303, 21753, 15019, -1701,
+	-2300, 21711, 15063, -1706, -2298, 21669, 15107, -1710, -2295, 21626, 15152, -1715, -2292, 21584, 15196, -1720,
+	-2290, 21542, 15241, -1725, -2287, 21500, 15285, -1730, -2284, 21458, 15329, -1735, -2282, 21416, 15374, -1740,
+	-2279, 21374, 15418, -1745, -2276, 21331, 15463, -1750, -2274, 21289, 15507, -1754, -2271, 21246, 15552, -1759,
+	-2268, 21204, 15596, -1764, -2265, 21162, 15640, -1769, -2262, 21119, 15685, -1774, -2259, 21076, 15729, -1778,
+	-2257, 21034, 15774, -1783, -2254, 20992, 15818, -1788, -2251, 20949, 15863, -1793, -2248, 20906, 15907, -1797,
+	-2245, 20863, 15952, -1802, -2242, 20821, 15996, -1807, -2239, 20779, 16040, -1812, -2236, 20735, 16085, -1816,
+	-2233, 20693, 16129, -1821, -2230, 20650, 16174, -1826, -2227, 20607, 16218, -1830, -2223, 20563, 16263, -1835,
+	-2220, 20521, 16307, -1840, -2217, 20478, 16351, -1844, -2214, 20435, 16396, -1849, -2211, 20393, 16440, -1854,
+	-2208, 20349, 16485, -1858, -2204, 20306, 16529, -1863, -2201, 20262, 16574, -1867, -2198, 20220, 16618, -1872,
+	-2195, 20177, 16662, -1876, -2191, 20133, 16707, -1881, -2188, 20091, 16751, -1886, -2185, 20047, 16796, -1890,
+	-2181, 20004, 16840, -1895, -2178, 19961, 16884, -1899, -2174, 19917, 16929, -1904, -2171, 19874, 16973, -1908,
+	-2168, 19831, 17018, -1913, -2164, 19787, 17062, -1917, -2161, 19744, 17106, -1921, -2157, 19700, 17151, -1926,
+	-2154, 19657, 17195, -1930, -2150, 19614, 17239, -1935, -2146, 19569, 17284, -1939, -2143, 19526, 17328, -1943,
+	-2139, 19483, 17372, -1948, -2136, 19440, 17416, -1952, -2132, 19395, 17461, -1956, -2128, 19352, 17505, -1961,
+	-2125, 19309, 17549, -1965, -2121, 19265, 17593, -1969, -2117, 19221, 17638, -1974, -2114, 19178, 17682, -1978,
+	-2110, 19134, 17726, -1982, -2106, 19090, 17770, -1986, -2102, 19046, 17815, -1991, -2099, 19003, 17859, -1995,
+	-2095, 18959, 17903, -1999, -2091, 18915, 17947, -2003, -2087, 18871, 17991, -2007, -2083, 18827, 18035, -2011,
+	-2079, 18783, 18080, -2016, -2076, 18740, 18124, -2020, -2072, 18696, 18168, -2024, -2068, 18652, 18212, -2028,
+	-2064, 18608, 18256, -2032, -2060, 18564, 18300, -2036, -2056, 18520, 18344, -2040, -2052, 18476, 18388, -2044,
+	-2048, 18432, 18432, -2048, -2044, 18388, 18476, -2052, -2040, 18344, 18520, -2056, -2036, 18300, 18564, -2060,
+	-2032, 18256, 18608, -2064, -2028, 18212, 18652, -2068, -2024, 18168, 18696, -2072, -2020, 18124, 18740, -2076,
+	-2016, 18080, 18783, -2079, -2011, 18035, 18827, -2083, -2007, 17991, 18871, -2087, -2003, 17947, 18915, -2091,
+	-1999, 17903, 18959, -2095, -1995, 17859, 19003, -2099, -1991, 17815, 19046, -2102, -1986, 17770, 19090, -2106,
+	-1982, 17726, 19134, -2110, -1978, 17682, 19178, -2114, -1974, 17638, 19221, -2117, -1969, 17593, 19265, -2121,
+	-1965, 17549, 19309, -2125, -1961, 17505, 19352, -2128, -1956, 17461, 19395, -2132, -1952, 17416, 19440, -2136,
+	-1948, 17372, 19483, -2139, -1943, 17328, 19526, -2143, -1939, 17284, 19569, -2146, -1935, 17239, 19614, -2150,
+	-1930, 17195, 19657, -2154, -1926, 17151, 19700, -2157, -1921, 17106, 19744, -2161, -1917, 17062, 19787, -2164,
+	-1913, 17018, 19831, -2168, -1908, 16973, 19874, -2171, -1904, 16929, 19917, -2174, -1899, 16884, 19961, -2178,
+	-1895, 16840, 20004, -2181, -1890, 16796, 20047, -2185, -1886, 16751, 20091, -2188, -1881, 16707, 20133, -2191,
+	-1876, 16662, 20177, -2195, -1872, 16618, 20220, -2198, -1867, 16574, 20262, -2201, -1863, 16529, 20306, -2204,
+	-1858, 16485, 20349, -2208, -1854, 16440, 20393, -2211, -1849, 16396, 20435, -2214, -1844, 16351, 20478, -2217,
+	-1840, 16307, 20521, -2220, -1835, 16263, 20563, -2223, -1830, 16218, 20607, -2227, -1826, 16174, 20650, -2230,
+	-1821, 16129, 20693, -2233, -1816, 16085, 20735, -2236, -1812, 16040, 20779, -2239, -1807, 15996, 20821, -2242,
+	-1802, 15952, 20863, -2245, -1797, 15907, 20906, -2248, -1793, 15863, 20949, -2251, -1788, 15818, 20992, -2254,
+	-1783, 15774, 21034, -2257, -1778, 15729, 21076, -2259, -1774, 15685, 21119, -2262, -1769, 15640, 21162, -2265,
+	-1764, 15596, 21204, -2268, -1759, 15552, 21246, -2271, -1754, 15507, 21289, -2274, -1750, 15463, 21331, -2276,
+	-1745, 15418, 21374, -2279, -1740, 15374, 21416, -2282, -1735, 15329, 21458, -2284, -1730, 15285, 21500, -2287,
+	-1725, 15241, 21542, -2290, -1720, 15196, 21584, -2292, -1715, 15152, 21626, -2295, -1710, 15107, 21669, -2298,
+	-1706, 15063, 21711, -2300, -1701, 15019, 21753, -2303, -1696, 14974, 21795, -2305, -1691, 14930, 21837, -2308,
+	-1686, 14885, 21879, -2310, -1681, 14841, 21921, -2313, -1676, 14797, 21962, -2315, -1671, 14752, 22004, -2317,
+	-1666, 14708, 22046, -2320, -1661, 14664, 22087, -2322, -1656, 14619, 22130, -2325, -1651, 14575, 22171, -2327,
+	-1646, 14531, 22212, -2329, -1641, 14486, 22254, -2331, -1636, 14442, 22296, -2334, -1631, 14398, 22337, -2336,
+	-1626, 14354, 22378, -2338, -1621, 14309, 22420, -2340, -1616, 14265, 22461, -2342, -1611, 14221, 22502, -2344,
+	-1606, 14177, 22544, -2347, -1600, 14132, 22585, -2349, -1595, 14088, 22626, -2351, -1590, 14044, 22667, -2353,
+	-1585, 14000, 22708, -2355, -1580, 13955, 22750, -2357, -1575, 13911, 22791, -2359, -1570, 13867, 22831, -2360,
+	-1565, 13823, 22872, -2362, -1560, 13779, 22913, -2364, -1554, 13735, 22953, -2366, -1549, 13691, 22994, -2368,
+	-1544, 13647, 23035, -2370, -1539, 13602, 23076, -2371, -1534, 13558, 23117, -2373, -1529, 13514, 23158, -2375,
+	-1523, 13470, 23198, -2377, -1518, 13426, 23238, -2378, -1513, 13382, 23279, -2380, -1508, 13338, 23319, -2381,
+	-1503, 13294, 23360, -2383, -1497, 13250, 23400, -2385, -1492, 13206, 23440, -2386, -1487, 13163, 23480, -2388,
+	-1482, 13119, 23520, -2389, -1477, 13075, 23561, -2391, -1471, 13031, 23600, -2392, -1466, 12987, 23640, -2393,
+	-1461, 12943, 23681, -2395, -1456, 12899, 23721, -2396, -1450, 12856, 23759, -2397, -1445, 12812, 23800, -2399,
+	-1440, 12768, 23840, -2400, -1435, 12724, 23880, -2401, -1429, 12681, 23918, -2402, -1424, 12637, 23959, -2404,
+	-1419, 12593, 23999, -2405, -1414, 12549, 24039, -2406, -1408, 12506, 24077, -2407, -1403, 12462, 24117, -2408,
+	-1398, 12419, 24156, -2409, -1393, 12375, 24196, -2410, -1387, 12332, 24234, -2411, -1382, 12288, 24274, -2412,
+	-1377, 12244, 24314, -2413, -1371, 12201, 24352, -2414, -1366, 12158, 24391, -2415, -1361, 12114, 24431, -2416,
+	-1356, 12071, 24469, -2416, -1350, 12027, 24508, -2417, -1345, 11984, 24547, -2418, -1340, 11941, 24586, -2419,
+	-1334, 11897, 24624, -2419, -1329, 11854, 24663, -2420, -1324, 11811, 24702, -2421, -1318, 11767, 24740, -2421,
+	-1313, 11724, 24779, -2422, -1308, 11681, 24817, -2422, -1302, 11638, 24855, -2423, -1297, 11595, 24893, -2423,
+	-1292, 11552, 24932, -2424, -1286, 11509, 24969, -2424, -1281, 11466, 25008, -2425, -1276, 11422, 25047, -2425,
+	-1271, 11380, 25085, -2426, -1265, 11337, 25122, -2426, -1260, 11294, 25160, -2426, -1255, 11251, 25198, -2426,
+	-1249, 11208, 25236, -2427, -1244, 11165, 25274, -2427, -1239, 11122, 25312, -2427, -1233, 11079, 25349, -2427,
+	-1228, 11037, 25386, -2427, -1223, 10994, 25424, -2427, -1217, 10951, 25461, -2427, -1212, 10908, 25499, -2427,
+	-1207, 10866, 25536, -2427, -1201, 10823, 25573, -2427, -1196, 10781, 25610, -2427, -1191, 10738, 25648, -2427,
+	-1185, 10696, 25684, -2427, -1180, 10653, 25722, -2427, -1175, 10611, 25758, -2426, -1169, 10568, 25795, -2426,
+	-1164, 10526, 25832, -2426, -1159, 10483, 25870, -2426, -1153, 10441, 25905, -2425, -1148, 10399, 25942, -2425,
+	-1143, 10357, 25978, -2424, -1137, 10314, 26015, -2424, -1132, 10272, 26052, -2424, -1127, 10230, 26088, -2423,
+	-1121, 10188, 26123, -2422, -1116, 10146, 26160, -2422, -1111, 10104, 26196, -2421, -1105, 10062, 26232, -2421,
+	-1100, 10020, 26268, -2420, -1095,  9978, 26304, -2419, -1089,  9936, 26340, -2419, -1084,  9894, 26376, -2418,
+	-1079,  9853, 26411, -2417, -1073,  9811, 26446, -2416, -1068,  9769, 26482, -2415, -1063,  9727, 26518, -2414,
+	-1058,  9686, 26553, -2413, -1052,  9644, 26588, -2412, -1047,  9603, 26623, -2411, -1042,  9561, 26659, -2410,
+	-1036,  9520, 26693, -2409, -1031,  9478, 26729, -2408, -1026,  9437, 26764, -2407, -1021,  9395, 26800, -2406,
+	-1015,  9354, 26834, -2405, -1010,  9313, 26868, -2403, -1005,  9271, 26904, -2402, -1000,  9230, 26939, -2401,
+	 -994,  9189, 26972, -2399,  -989,  9148, 27007, -2398,  -984,  9107, 27042, -2397,  -979,  9066, 27076, -2395,
+	 -973,  9025, 27110, -2394,  -968,  8984, 27144, -2392,  -963,  8943, 27179, -2391,  -958,  8902, 27213, -2389,
+	 -952,  8861, 27246, -2387,  -947,  8821, 27280, -2386,  -942,  8780, 27314, -2384,  -937,  8739, 27348, -2382,
+	 -932,  8699, 27382, -2381,  -926,  8658, 27415, -2379,  -921,  8617, 27449, -2377,  -916,  8577, 27482, -2375,
+	 -911,  8536, 27516, -2373,  -906,  8496, 27549, -2371,  -900,  8456, 27581, -2369,  -895,  8415, 27615, -2367,
+	 -890,  8375, 27648, -2365,  -885,  8335, 27681, -2363,  -880,  8295, 27714, -2361,  -875,  8255, 27747, -2359,
+	 -869,  8215, 27778, -2356,  -864,  8175, 27811, -2354,  -859,  8135, 27844, -2352,  -854,  8095, 27876, -2349,
+	 -849,  8055, 27909, -2347,  -844,  8015, 27942, -2345,  -839,  7975, 27974, -2342,  -834,  7936, 28006, -2340,
+	 -829,  7896, 28038, -2337,  -823,  7856, 28070, -2335,  -818,  7817, 28101, -2332,  -813,  7777, 28133, -2329,
+	 -808,  7738, 28165, -2327,  -803,  7698, 28197, -2324,  -798,  7659, 28228, -2321,  -793,  7620, 28260, -2319,
+	 -788,  7580, 28292, -2316,  -783,  7541, 28323, -2313,  -778,  7502, 28354, -2310,  -773,  7463, 28385, -2307,
+	 -768,  7424, 28416, -2304,  -763,  7385, 28447, -2301,  -758,  7346, 28478, -2298,  -753,  7307, 28509, -2295,
+	 -748,  7268, 28540, -2292,  -743,  7230, 28570, -2289,  -738,  7191, 28600, -2285,  -733,  7152, 28631, -2282,
+	 -728,  7114, 28661, -2279,  -723,  7075, 28691, -2275,  -718,  7037, 28721, -2272,  -713,  6998, 28752, -2269,
+	 -709,  6960, 28782, -2265,  -704,  6922, 28812, -2262,  -699,  6883, 28842, -2258,  -694,  6845, 28872, -2255,
+	 -689,  6807, 28901, -2251,  -684,  6769, 28930, -2247,  -679,  6731, 28960, -2244,  -675,  6693, 28990, -2240,
+	 -670,  6655, 29019, -2236,  -665,  6617, 29048, -2232,  -660,  6580, 29076, -2228,  -655,  6542, 29105, -2224,
+	 -650,  6504, 29135, -2221,  -646,  6467, 29164, -2217,  -641,  6429, 29193, -2213,  -636,  6392, 29220, -2208,
+	 -631,  6354, 29249, -2204,  -627,  6317, 29278, -2200,  -622,  6280, 29306, -2196,  -617,  6243, 29334, -2192,
+	 -613,  6206, 29363, -2188,  -608,  6168, 29391, -2183,  -603,  6131, 29419, -2179,  -598,  6094, 29446, -2174,
+	 -594,  6058, 29474, -2170,  -589,  6021, 29501, -2165,  -584,  5984, 29529, -2161,  -580,  5947, 29557, -2156,
+	 -575,  5911, 29584, -2152,  -571,  5874, 29612, -2147,  -566,  5838, 29638, -2142,  -561,  5801, 29666, -2138,
+	 -557,  5765, 29693, -2133,  -552,  5729, 29719, -2128,  -548,  5692, 29747, -2123,  -543,  5656, 29773, -2118,
+	 -539,  5620, 29800, -2113,  -534,  5584, 29826, -2108,  -530,  5548, 29853, -2103,  -525,  5512, 29879, -2098,
+	 -521,  5476, 29906, -2093,  -516,  5441, 29931, -2088,  -512,  5405, 29958, -2083,  -507,  5369, 29983, -2077,
+	 -503,  5334, 30009, -2072,  -499,  5298, 30036, -2067,  -494,  5263, 30060, -2061,  -490,  5228, 30086, -2056,
+	 -485,  5192, 30111, -2050,  -481,  5157, 30137, -2045,  -477,  5122, 30162, -2039,  -472,  5087, 30187, -2034,
+	 -468,  5052, 30212, -2028,  -464,  5017, 30237, -2022,  -459,  4982, 30262, -2017,  -455,  4948, 30286, -2011,
+	 -451,  4913, 30311, -2005,  -447,  4878, 30336, -1999,  -442,  4844, 30359, -1993,  -438,  4809, 30384, -1987,
+	 -434,  4775, 30408, -1981,  -430,  4741, 30432, -1975,  -426,  4706, 30457, -1969,  -421,  4672, 30480, -1963,
+	 -417,  4638, 30503, -1956,  -413,  4604, 30527, -1950,  -409,  4570, 30551, -1944,  -405,  4536, 30575, -1938,
+	 -401,  4502, 30598, -1931,  -397,  4469, 30621, -1925,  -393,  4435, 30644, -1918,  -389,  4402, 30667, -1912,
+	 -385,  4368, 30690, -1905,  -381,  4335, 30713, -1899,  -377,  4301, 30736, -1892,  -373,  4268, 30758, -1885,
+	 -369,  4235, 30780, -1878,  -365,  4202, 30803, -1872,  -361,  4169, 30825, -1865,  -357,  4136, 30847, -1858,
+	 -353,  4103, 30869, -1851,  -349,  4070, 30891, -1844,  -345,  4038, 30912, -1837,  -341,  4005, 30934, -1830,
+	 -338,  3973, 30956, -1823,  -334,  3940, 30977, -1815,  -330,  3908, 30998, -1808,  -326,  3875, 31020, -1801,
+	 -322,  3843, 31040, -1793,  -319,  3811, 31062, -1786,  -315,  3779, 31083, -1779,  -311,  3747, 31103, -1771,
+	 -307,  3715, 31124, -1764,  -304,  3683, 31145, -1756,  -300,  3652, 31164, -1748,  -296,  3620, 31185, -1741,
+	 -293,  3589, 31205, -1733,  -289,  3557, 31225, -1725,  -286,  3526, 31245, -1717,  -282,  3495, 31264, -1709,
+	 -278,  3463, 31285, -1702,  -275,  3432, 31305, -1694,  -271,  3401, 31324, -1686,  -268,  3370, 31343, -1677,
+	 -264,  3339, 31362, -1669,  -261,  3309, 31381, -1661,  -257,  3278, 31400, -1653,  -254,  3247, 31420, -1645,
+	 -251,  3217, 31438, -1636,  -247,  3186, 31457, -1628,  -244,  3156, 31476, -1620,  -240,  3126, 31493, -1611,
+	 -237,  3096, 31512, -1603,  -234,  3066, 31530, -1594,  -231,  3036, 31548, -1585,  -227,  3006, 31566, -1577,
+	 -224,  2976, 31584, -1568,  -221,  2946, 31602, -1559,  -218,  2917, 31619, -1550,  -214,  2887, 31637, -1542,
+	 -211,  2858, 31654, -1533,  -208,  2828, 31672, -1524,  -205,  2799, 31689, -1515,  -202,  2770, 31706, -1506,
+	 -199,  2741, 31722, -1496,  -196,  2712, 31739, -1487,  -192,  2683, 31755, -1478,  -189,  2654, 31772, -1469,
+	 -186,  2626, 31787, -1459,  -183,  2597, 31804, -1450,  -180,  2568, 31820, -1440,  -177,  2540, 31836, -1431,
+	 -175,  2512, 31852, -1421,  -172,  2483, 31869, -1412,  -169,  2455, 31884, -1402,  -166,  2427, 31899, -1392,
+	 -163,  2399, 31915, -1383,  -160,  2371, 31930, -1373,  -157,  2344, 31944, -1363,  -155,  2316, 31960, -1353,
+	 -152,  2289, 31974, -1343,  -149,  2261, 31989, -1333,  -146,  2234, 32003, -1323,  -144,  2206, 32019, -1313,
+	 -141,  2179, 32033, -1303,  -138,  2152, 32047, -1293,  -136,  2125, 32061, -1282,  -133,  2098, 32075, -1272,
+	 -131,  2072, 32089, -1262,  -128,  2045, 32102, -1251,  -125,  2018, 32116, -1241,  -123,  1992, 32129, -1230,
+	 -120,  1965, 32142, -1219,  -118,  1939, 32156, -1209,  -115,  1913, 32168, -1198,  -113,  1887, 32181, -1187,
+	 -111,  1861, 32194, -1176,  -108,  1835, 32207, -1166,  -106,  1809, 32220, -1155,  -104,  1783, 32233, -1144,
+	 -101,  1758, 32244, -1133,   -99,  1732, 32256, -1121,   -97,  1707, 32268, -1110,   -94,  1682, 32279, -1099,
+	  -92,  1657, 32291, -1088,   -90,  1631, 32303, -1076,   -88,  1607, 32314, -1065,   -86,  1582, 32326, -1054,
+	  -84,  1557, 32337, -1042,   -81,  1532, 32348, -1031,   -79,  1508, 32358, -1019,   -77,  1483, 32369, -1007,
+	  -75,  1459, 32380,  -996,   -73,  1435, 32390,  -984,   -71,  1411, 32400,  -972,   -69,  1387, 32410,  -960,
+	  -67,  1363, 32420,  -948,   -66,  1339, 32431,  -936,   -64,  1315, 32441,  -924,   -62,  1291, 32451,  -912,
+	  -60,  1268, 32460,  -900,   -58,  1245, 32469,  -888,   -56,  1221, 32479,  -876,   -55,  1198, 32488,  -863,
+	  -53,  1175, 32497,  -851,   -51,  1152, 32505,  -838,   -50,  1129, 32515,  -826,   -48,  1107, 32522,  -813,
+	  -46,  1084, 32531,  -801,   -45,  1061, 32540,  -788,   -43,  1039, 32547,  -775,   -42,  1017, 32555,  -762,
+	  -40,   995, 32563,  -750,   -39,   972, 32572,  -737,   -37,   951, 32578,  -724,   -36,   929, 32586,  -711,
+	  -34,   907, 32593,  -698,   -33,   885, 32601,  -685,   -32,   864, 32607,  -671,   -30,   842, 32614,  -658,
+	  -29,   821, 32621,  -645,   -28,   800, 32627,  -631,   -26,   779, 32633,  -618,   -25,   758, 32640,  -605,
+	  -24,   737, 32646,  -591,   -23,   716, 32652,  -577,   -22,   696, 32658,  -564,   -21,   675, 32664,  -550,
+	  -20,   655, 32669,  -536,   -18,   635, 32673,  -522,   -17,   614, 32679,  -508,   -16,   594, 32685,  -495,
+	  -16,   575, 32690,  -481,   -15,   555, 32694,  -466,   -14,   535, 32699,  -452,   -13,   515, 32704,  -438,
+	  -12,   496, 32708,  -424,   -11,   477, 32712,  -410,   -10,   457, 32716,  -395,   -10,   438, 32721,  -381,
+	   -9,   419, 32724,  -366,    -8,   401, 32727,  -352,    -7,   382, 32730,  -337,    -7,   363, 32734,  -322,
+	   -6,   345, 32737,  -308,    -6,   326, 32741,  -293,    -5,   308, 32743,  -278,    -4,   290, 32745,  -263,
+	   -4,   272, 32748,  -248,    -3,   254, 32750,  -233,    -3,   236, 32753,  -218,    -3,   218, 32756,  -203,
+	   -2,   201, 32757,  -188,    -2,   184, 32758,  -172,    -2,   166, 32761,  -157,    -1,   149, 32761,  -141,
+	   -1,   132, 32763,  -126,    -1,   115, 32764,  -110,    -1,    98, 32766,   -95,     0,    82, 32765,   -79,
+	    0,    65, 32767,   -64,     0,    49, 32767,   -48,     0,    32, 32767,   -32,     0,    16, 32767,   -16
 };
 
 #endif
--- a/src/ft2_intrp_table.h
+++ b/src/ft2_intrp_table.h
@@ -13,8 +13,8 @@
 
 #else
 
-#define CUBIC_PHASES 512
-#define CUBIC_PHASES_BITS 9
+#define CUBIC_PHASES 1024
+#define CUBIC_PHASES_BITS 10
 
 #endif
 
--- a/src/ft2_mix_macros.h
+++ b/src/ft2_mix_macros.h
@@ -124,7 +124,7 @@
 	*audioMixL++ += sample; \
 	*audioMixR++ += sample; \
 
-// 4-tap cubic spline interpolation (default - slower than linear, but better quality)
+// 4-tap cubic spline interpolation
 
 // in: int32_t s0,s1,s2,s3 = -128..127 | f = 0..65535 (frac) | out: 16-bit s0 (will exceed 16-bits because of overshoot)
 #define INTERPOLATE8(s0, s1, s2, s3, f) \
--- a/src/ft2_palette.c
+++ b/src/ft2_palette.c
@@ -27,7 +27,7 @@
 
 void setPal16(pal16 *p, bool redrawScreen)
 {
-#define LOOP_PIN_COL_SUB 75
+#define LOOP_PIN_COL_SUB 96
 #define TEXT_MARK_COLOR 0x0078D7
 #define BOX_SELECT_COLOR 0x7F7F7F
 
--- a/src/ft2_pattern_ed.c
+++ b/src/ft2_pattern_ed.c
@@ -2155,9 +2155,10 @@
 	}
 	else
 	{
-		if (val > 999)
-			val = 999;
+		if (val > MAX_BPM)
+			val = MAX_BPM;
 
+		assert(MAX_BPM == 999);
 		str[0] = '0' + (char)(val / 100);
 		str[1] = '0' + ((val / 10) % 10);
 		str[2] = '0' + (val % 10);
--- a/src/ft2_replayer.c
+++ b/src/ft2_replayer.c
@@ -30,7 +30,7 @@
 ** FT2 obviously didn't have such big tables.
 */
 
-static uint32_t musicTimeTab[1000];
+static uint32_t musicTimeTab[MAX_BPM+1];
 static uint64_t period2ScopeDeltaTab[65536];
 static double dLogTab[768], dLogTabMul[32], dAudioRateFactor;
 
@@ -392,27 +392,47 @@
 		dLogTabMul[i] = exp2(-i);
 }
 
-void calcReplayRate(int32_t rate)
+void calcReplayRate(int32_t audioFreq)
 {
 	int32_t i;
 
-	if (rate == 0)
+	if (audioFreq == 0)
 		return;
-	
-	dAudioRateFactor = (double)MIXER_FRAC_SCALE / rate;
 
-	audio.quickVolSizeVal = rate / 200; // FT2 truncates here
+	dAudioRateFactor = (double)MIXER_FRAC_SCALE / audioFreq;
+
+	audio.quickVolSizeVal = audioFreq / 200; // FT2 truncates here
 	audio.rampQuickVolMul = (int32_t)(((UINT32_MAX + 1.0) / audio.quickVolSizeVal) + 0.5);
-	audio.dSpeedValMul = editor.dPerfFreq / rate; // for audio/video sync
+	audio.dSpeedValMul = editor.dPerfFreq / audioFreq; // for audio/video sync
 
+	/* Calculate tables to prevent floating point operations on systems that
+	** might have a slow FPU. This is quite hackish and not really needed,
+	** but it doesn't take up THAT much RAM anyway.
+	*/
+
 	// calculate table used to count replayer time (displayed as hours/minutes/seconds)
-	const double dMul = (UINT32_MAX + 1.0) / rate;
+	const double dMul = (UINT32_MAX + 1.0) / audioFreq;
+
+	audio.speedValTab[0] = 0;
 	musicTimeTab[0] = UINT32_MAX;
-	for (i = 1; i < 1000; i++)
+	audio.rampSpeedValMulTab[0] = UINT32_MAX;
+	audio.tickTimeLengthTab[0] = (uint64_t)UINT32_MAX << 32;
+
+	const double dTickTimeLenMul = audio.dSpeedValMul * (UINT32_MAX + 1.0);
+	for (i = 1; i <= MAX_BPM; i++)
 	{
-		uint32_t samplesPerTick = ((rate + rate) + (rate >> 1)) / i; // exactly how setSpeed() calculates it
-		const double dVal = samplesPerTick * dMul;
-		musicTimeTab[i] = (uint32_t)(dVal + 0.5);
+		int32_t samplesPerTick = (int32_t)(((audioFreq * 2.5) / i) + 0.5); // rounded
+
+		audio.speedValTab[i] = samplesPerTick;
+
+		// used for song playback counter (hh:mm:ss)
+		musicTimeTab[i] = (uint32_t)((samplesPerTick * dMul) + 0.5);
+
+		// number of samples per tick -> tick length for performance counter (syncing visuals to audio)
+		audio.tickTimeLengthTab[i] = (uint64_t)(samplesPerTick * dTickTimeLenMul);
+
+		// for calculating volume ramp length for "tick" ramps
+		audio.rampSpeedValMulTab[i] = (int32_t)(((UINT32_MAX + 1.0) / samplesPerTick) + 0.5);
 	}
 
 	calcPeriod2DeltaTables();
@@ -2063,7 +2083,8 @@
 
 	if (song.pattDelTime2 > 0)
 	{
-		if (--song.pattDelTime2 > 0)
+		song.pattDelTime2--;
+		if (song.pattDelTime2 > 0)
 			song.pattPos--;
 	}
 
@@ -2086,13 +2107,10 @@
 				song.songPos = 0;
 				bxxOverflow = false;
 			}
-			else
+			else if (++song.songPos >= song.len)
 			{
-				if (++song.songPos >= song.len)
-				{
-					editor.wavReachedEndFlag = true;
-					song.songPos = song.repS;
-				}
+				editor.wavReachedEndFlag = true;
+				song.songPos = song.repS;
 			}
 
 			assert(song.songPos <= 255);
@@ -2135,11 +2153,13 @@
 		return;
 	}
 
-	assert(song.speed >= 1 && song.speed <= 999);
-	song.musicTime64 += musicTimeTab[song.speed]; // for playback counter
+	assert(song.speed >= MIN_BPM && song.speed <= MAX_BPM);
+	song.musicTime64 += musicTimeTab[song.speed]; // for song playback counter (hh:mm:ss)
 
 	readNewNote = false;
-	if (--song.timer == 0)
+
+	song.timer--;
+	if (song.timer == 0)
 	{
 		song.timer = song.tempo;
 		readNewNote = true;
@@ -3240,8 +3260,6 @@
 	// handle channel sync queue
 
 	while (chQueueClearing);
-
-	chQueueReading = true;
 	while (chQueueReadSize() > 0)
 	{
 		if (frameTime64 < getChQueueTimestamp())
@@ -3257,10 +3275,10 @@
 		if (!chQueuePop())
 			break;
 	}
-	chQueueReading = false;
 
-	/* extra validation because of possible issues when the buffer is full
-	** and positions are being reset, which is not entirely thread safe. */
+	/* Extra validation because of possible issues when the buffer is full
+	** and positions are being reset, which is not entirely thread safe.
+	*/
 	if (chSyncEntry != NULL && chSyncEntry->timestamp == 0)
 		chSyncEntry = NULL;
 
@@ -3267,8 +3285,6 @@
 	// handle pattern sync queue
 
 	while (pattQueueClearing);
-
-	pattQueueReading = true;
 	while (pattQueueReadSize() > 0)
 	{
 		if (frameTime64 < getPattQueueTimestamp())
@@ -3281,10 +3297,10 @@
 		if (!pattQueuePop())
 			break;
 	}
-	pattQueueReading = false;
 
-	/* extra validation because of possible issues when the buffer is full
-	** and positions are being reset, which is not entirely thread safe. */
+	/* Extra validation because of possible issues when the buffer is full
+	** and positions are being reset, which is not entirely thread safe.
+	*/
 	if (pattSyncEntry != NULL && pattSyncEntry->timestamp == 0)
 		pattSyncEntry = NULL;
 
--- a/src/ft2_replayer.h
+++ b/src/ft2_replayer.h
@@ -33,7 +33,8 @@
 };
 
 // DO NOT TOUCH!
-#define MIN_BPM 32
+#define MIN_BPM 1
+#define MAX_BPM 999
 #define MAX_VOICES 32
 #define TRACK_WIDTH (5 * MAX_VOICES)
 #define MAX_NOTES ((12 * 10 * 16) + 16)
--- a/src/ft2_sample_loader.c
+++ b/src/ft2_sample_loader.c
@@ -845,7 +845,7 @@
 		bodyLen = filesize - bodyPtr;
 
 	fseek(f, vhdrPtr, SEEK_SET);
-	fread(&sampleLoopStart,  4, 1, f); sampleLoopStart  = SWAP32(sampleLoopStart);
+	fread(&sampleLoopStart,  4, 1, f); sampleLoopStart = SWAP32(sampleLoopStart);
 	fread(&sampleLoopLength, 4, 1, f); sampleLoopLength = SWAP32(sampleLoopLength);
 	fseek(f, 4, SEEK_CUR);
 	fread(&sampleRate, 2, 1, f); sampleRate = SWAP16(sampleRate);
--- a/src/ft2_wav_renderer.c
+++ b/src/ft2_wav_renderer.c
@@ -168,7 +168,7 @@
 {
 	uint32_t maxSamplesPerTick, sampleSize;
 
-	maxSamplesPerTick = ((frq * 5) / 2) / MIN_BPM; // absolute max samples per tidck
+	maxSamplesPerTick = (int32_t)ceil((frq * 2.5) / MIN_BPM); // absolute max samples per tick
 	sampleSize = (WDBitDepth / 8) * 2; // 2 channels
 
 	// *2 for stereo