/*
 * SBM_pitchBased.c
 *
 *  Created on: 2020. 3. 12.
 *      Author: kc.gajula
 */


#include "SeamlessBufferManagement.h"
typedef long long INT64;

extern int *sbm_buf_left;
extern int *sbm_buf_right;


extern int wridx;
extern int rdidx0;
extern int rdidx1;
extern int winpos;
extern int r;
extern  FramePitchGain_T Pg_0, Pg_m1;
extern Speed_Proc_State_T Speed_Proc_State;
extern int sbm_internal_count;
extern int oFsz;
#ifndef DISABLETRANSITION
extern int transition_flag;
#endif
extern int  gain_crfade,delta_crfade, pitch_prot_cnt,flagEnabled_CROSSFADE_Fin, ssc_mono_sum_info, PitchIsStable;
extern int win[SPEEDPIV_WINLEN / 2+1];
static int Scratch1[SBM_MAX_OUTPUT_NUM];
static int Scratch2[SBM_MAX_OUTPUT_NUM];
extern int buf_lvl_offset_prot;
int IncrSlow;
int IncrFast;
extern int SBM_NORMAL_OUTPUT_NUM;
extern int SBM_FAST_OUTPUT_NUM;
extern int  SBM_SLOW_OUTPUT_NUM;
static int DecIntSamplesMono(int *out1ptr, int bup_n, int nout)
{
	oFsz = bup_n;
	int d = (1 << 24);
	int i = 0;
	int j = 0;
	INT64 k = 0;
	if (nout == SBM_SLOW_OUTPUT_NUM)
		d = IncrSlow;
	else if (nout == SBM_FAST_OUTPUT_NUM)
		d = IncrFast;

	do {
		Scratch1[i] = out1ptr[j];
		i++;
		k = k + d;
		j = (int)(k >> 24);
	} while (i < bup_n);
	do {
		i--;
		out1ptr[i] = Scratch1[i];
	} while (i > 0);
	nout = bup_n;
	return nout;
}
static int DecIntSamplesStereo(int *out1ptr, int *out2ptr, int bup_n, int nout)
{
	oFsz = bup_n;
	int d = (1 << 24);
	int i = 0;
	int j = 0;
	INT64 k = 0;
	if (nout == SBM_SLOW_OUTPUT_NUM)
		d = IncrSlow;
	else if (nout == SBM_FAST_OUTPUT_NUM)
		d = IncrFast;

	do {
		Scratch1[i] = out1ptr[j];
		Scratch2[i] = out2ptr[j];
		i++;
		k = k + d;
		j = (int)(k >> 24);
	} while (i < bup_n);
	do {
		i--;
		out1ptr[i] = Scratch1[i];
		out2ptr[i] = Scratch2[i];
	} while (i > 0);
	nout = bup_n;
	return nout;
}
 int Speed_Proc_State_NML_stereo(int *out1, int *out2, int n, int winpoAftern, int signr, int Pitch_Ok)
{
	int wincntr = winpoAftern - ((SPEEDPIV_WINLEN << 16) / 2);
	int rdidx = rdidx0 + n; if (rdidx > (winpoAftern >> 16)) rdidx -= SPEEDPIV_BUFLEN; if ((rdidx < (winpoAftern >> 16) - SPEEDPIV_BUFLEN)) rdidx += SPEEDPIV_BUFLEN;
	int alpha = (rdidx << 16) - wincntr;
	int nout = 0;
	int bup_n = n;
	int *out1ptr = out1;
	int *out2ptr = out2;
	int alt_r = r;
	if (signr*alpha > (DIST_THR_1 << 16))
	{
		if (Pitch_Ok)
		{
			if (Start_PitchCrossFade(Pg_0.Pitch, r))
			{
				Speed_Proc_State = SPEED_PROC_STATE_PROC_PITCH;
				return nout;
			}
			else
				Pitch_Ok = 0;
		}
	}
	wincntr = winpos - ((SPEEDPIV_WINLEN << 16) / 2);
	alpha = (rdidx0 << 16) - wincntr;/*CROSSFADE is applied for next frame*/
	if (((signr*alpha > (DIST_THR_2 << 16)) && (!Pitch_Ok)) && (sbm_internal_count < buf_lvl_offset_prot))
	{
		Start_UnconstrainedCrossfade(r); Speed_Proc_State = SPEED_PROC_STATE_PROC_CROSSFADE;
		if (rdidx1 > (winpos >> 16)) rdidx1 -= SPEEDPIV_BUFLEN;     if ((rdidx1 < (winpos >> 16) - SPEEDPIV_BUFLEN)) rdidx1 += SPEEDPIV_BUFLEN;
		return nout;
	}

	if (transition_flag == EFFECT_TO_NORMAL)
	{
		alt_r = ONE_Q16; oFsz = n;
	}
	do {
		int d;
		// write next sample

		if (++wridx >= SPEEDPIV_BUFLEN)
			wridx = 0;

		d = wridx - (winpos >> 16);
		d = ((d + SPEEDPIV_BUFLEN + SPEEDPIV_BUFLEN / 2) % SPEEDPIV_BUFLEN) - SPEEDPIV_BUFLEN / 2;


		while (d > 0)
		{
			int dl, dr;

			int wincntr = winpos - ((SPEEDPIV_WINLEN << 16) / 2);

			int alpha = (rdidx0 << 16) - wincntr;

			dl = sbm_buf_left[rdidx0];
			dr = sbm_buf_right[rdidx0];
			/*if (signr*alpha>(DIST_THR_1<<16))
			{
				if (Pitch_Ok) {if (Start_PitchCrossFade(Pg_0.Pitch,r)) Speed_Proc_State=SPEED_PROC_STATE_PROC_PITCH;}
			}
			if ((signr*alpha > (DIST_THR_2 << 16)) && (!Pitch_Ok))
			{
				Start_UnconstrainedCrossfade(r); Speed_Proc_State = SPEED_PROC_STATE_PROC_CROSSFADE;
			}*/

			*out1++ = dl;
			*out2++ = dr;


			nout++;     // increment output sample number

			// increment window pointer
			winpos += alt_r;
			if (winpos >= (SPEEDPIV_BUFLEN << 16)) winpos -= (SPEEDPIV_BUFLEN << 16);

			++rdidx0;   if (rdidx0 > (winpos >> 16)) rdidx0 -= SPEEDPIV_BUFLEN;     if ((rdidx0 < (winpos >> 16) - SPEEDPIV_BUFLEN)) rdidx0 += SPEEDPIV_BUFLEN;
			++rdidx1;   if (rdidx1 > (winpos >> 16)) rdidx1 -= SPEEDPIV_BUFLEN;     if ((rdidx1 < (winpos >> 16) - SPEEDPIV_BUFLEN)) rdidx1 += SPEEDPIV_BUFLEN;

			d = wridx - (winpos >> 16);
			d = ((d + SPEEDPIV_BUFLEN + SPEEDPIV_BUFLEN / 2) % SPEEDPIV_BUFLEN) - SPEEDPIV_BUFLEN / 2;
		}   //   while (d > 0)

	} while (--n > 0);   // do {
	/*Protection code to make during effect to normal the framework expects output samples as NORMAL case*/
	if ((transition_flag == EFFECT_TO_NORMAL) && nout != bup_n)
	{
		nout = DecIntSamplesStereo(out1ptr, out2ptr, bup_n, nout);
	}
	return nout;
}

 int Speed_Proc_State_PP_stereo(int *out1, int *out2, int n)
{
	int nout=0;
	int *out1ptr = out1;
	int *out2ptr = out2;
	int bup_n = n;
	if (gain_crfade <= 1)
	{
		gain_crfade = 0; Stop_PitchCrossFade(); Speed_Proc_State = SPEED_PROC_STATE_NORMAL; pitch_prot_cnt = 0; return nout;
	}

	do {
		int d;
		// write next sample

		if (++wridx >= SPEEDPIV_BUFLEN)
			wridx = 0;

		d = wridx - (winpos >> 16);
		d = ((d + SPEEDPIV_BUFLEN + SPEEDPIV_BUFLEN / 2) % SPEEDPIV_BUFLEN) - SPEEDPIV_BUFLEN / 2;


		while (d > 0)
		{
			int dl, dr;

			int wincntr = winpos - ((SPEEDPIV_WINLEN << 16) / 2);

			int alpha = (rdidx0 << 16) - wincntr;

			int mgain_crfade = (1 << 26) - gain_crfade;
			dl = (int)(((INT64)sbm_buf_left[rdidx0] * gain_crfade + (INT64)sbm_buf_left[rdidx1] * mgain_crfade + (1 << (26 - 1))) >> 26);
			dr = (int)(((INT64)sbm_buf_right[rdidx0] * gain_crfade + (INT64)sbm_buf_right[rdidx1] * mgain_crfade + (1 << (26 - 1))) >> 26);
			gain_crfade -= delta_crfade;
			if (gain_crfade < 0) { gain_crfade = 1; }


			*out1++ = dl;
			*out2++ = dr;

			// debug
			//*out2++ = Pitch0 * (1<<(6+6));
			//*out2++ = Pg_0.Gain * (1<<(6+0));
			//*out2++ = pitchstabstate * (1 << (6 + 6));
		//*out2++ = (Pitch_Ok ? 16384 : 0) << 6;
		//*out2++ = ((int)Speed_Proc_State<<13) << 6;

			nout++;     // increment output sample number

			// increment window pointer
			winpos += r;
			if (winpos >= (SPEEDPIV_BUFLEN << 16)) winpos -= (SPEEDPIV_BUFLEN << 16);

			++rdidx0;   if (rdidx0 > (winpos >> 16)) rdidx0 -= SPEEDPIV_BUFLEN;     if ((rdidx0 < (winpos >> 16) - SPEEDPIV_BUFLEN)) rdidx0 += SPEEDPIV_BUFLEN;
			++rdidx1;   if (rdidx1 > (winpos >> 16)) rdidx1 -= SPEEDPIV_BUFLEN;     if ((rdidx1 < (winpos >> 16) - SPEEDPIV_BUFLEN)) rdidx1 += SPEEDPIV_BUFLEN;

			d = wridx - (winpos >> 16);
			d = ((d + SPEEDPIV_BUFLEN + SPEEDPIV_BUFLEN / 2) % SPEEDPIV_BUFLEN) - SPEEDPIV_BUFLEN / 2;
		}   //   while (d > 0)

	} while (--n > 0);

	/*Protection code to make during effect to normal the framework expects output samples as NORMAL case*/
	if ((transition_flag == EFFECT_TO_NORMAL) && nout != bup_n)
	{
		nout = DecIntSamplesStereo(out1ptr, out2ptr, bup_n, nout);
	}
	return nout;
}

 int Speed_Proc_State_PCF_stereo(int *out1, int *out2, int n)
{
	int nout = 0;
	int idx_alpha = 0;
	int idx_beta = 0;
	int *out1ptr = out1;
	int *out2ptr = out2;
	int bup_n = n;
	if (flagEnabled_CROSSFADE_Fin) {
		Stop_UnconstrainedCrossFade(); Speed_Proc_State = SPEED_PROC_STATE_NORMAL; flagEnabled_CROSSFADE_Fin = 0; return  Speed_Proc_State;}

	do {
		int d;
		// write next sample

		if (++wridx >= SPEEDPIV_BUFLEN)
			wridx = 0;

		d = wridx - (winpos >> 16);
		d = ((d + SPEEDPIV_BUFLEN + SPEEDPIV_BUFLEN / 2) % SPEEDPIV_BUFLEN) - SPEEDPIV_BUFLEN / 2;


		while (d > 0)
		{
			int dl, dr;

			int wincntr = winpos - ((SPEEDPIV_WINLEN << 16) / 2);

			int alpha = (rdidx0 << 16) - wincntr;
			if (flagEnabled_CROSSFADE_Fin)
			{
				dl = sbm_buf_left[rdidx1];
				dr = sbm_buf_right[rdidx1];
			}
			else
			{
				alpha = ABS(alpha) - (DIST_THR_2 << 16);                 // alpha starts from 0
				idx_alpha = alpha >> (16 + 0);                  // integer part
				int gamma = alpha - (idx_alpha << (16 + 0));        // fractional part (Q(16+0))
				int gamma_m1 = (1 << (16 + 0)) - gamma;
				idx_alpha <<= 1;                                      // use prev table (2 times longer)
				alpha = (int)((((INT64)win[idx_alpha] * gamma_m1 + (INT64)win[idx_alpha + 1 * 2] * gamma)) >> (16 + 0));
				idx_beta = (SPEEDPIV_WINLEN / 2) - 1 * 2 - idx_alpha;
				int beta = (int)((((INT64)win[idx_beta] * gamma + (INT64)win[idx_beta + 1 * 2] * gamma_m1)) >> (16 + 0));
				dl = (int)(((INT64)sbm_buf_left[rdidx0] * beta + (INT64)sbm_buf_left[rdidx1] * alpha + (1 << (26 - 1))) >> 26);
				dr = (int)(((INT64)sbm_buf_right[rdidx0] * beta + (INT64)sbm_buf_right[rdidx1] * alpha + (1 << (26 - 1))) >> 26);
				if (idx_beta <= 1) { flagEnabled_CROSSFADE_Fin = 1; }
			}
			//if (idx_beta<=1) { Stop_UnconstrainedCrossFade(); Speed_Proc_State = SPEED_PROC_STATE_NORMAL; }
			*out1++ = dl;
			*out2++ = dr;

			// debug
			//*out2++ = Pitch0 * (1<<(6+6));
			//*out2++ = Pg_0.Gain * (1<<(6+0));
			//*out2++ = pitchstabstate * (1 << (6 + 6));
		//*out2++ = (Pitch_Ok ? 16384 : 0) << 6;
		//*out2++ = ((int)Speed_Proc_State<<13) << 6;

			nout++;     // increment output sample number

			// increment window pointer
			winpos += r;
			if (winpos >= (SPEEDPIV_BUFLEN << 16)) winpos -= (SPEEDPIV_BUFLEN << 16);

			++rdidx0;   if (rdidx0 > (winpos >> 16)) rdidx0 -= SPEEDPIV_BUFLEN;     if ((rdidx0 < (winpos >> 16) - SPEEDPIV_BUFLEN)) rdidx0 += SPEEDPIV_BUFLEN;
			++rdidx1;   if (rdidx1 > (winpos >> 16)) rdidx1 -= SPEEDPIV_BUFLEN;     if ((rdidx1 < (winpos >> 16) - SPEEDPIV_BUFLEN)) rdidx1 += SPEEDPIV_BUFLEN;

			d = wridx - (winpos >> 16);
			d = ((d + SPEEDPIV_BUFLEN + SPEEDPIV_BUFLEN / 2) % SPEEDPIV_BUFLEN) - SPEEDPIV_BUFLEN / 2;
		}   //   while (d > 0)

	} while (--n > 0);
	/*Protection code to make during effect to normal the framework expects output samples as NORMAL case*/
	if ((transition_flag == EFFECT_TO_NORMAL) && nout != bup_n)
	{
		nout = DecIntSamplesStereo(out1ptr, out2ptr, bup_n, nout);
	}
	return nout;
}

 int Speed_Proc_State_NML_mono(int *out1, int n, int winpoAftern, int signr, int Pitch_Ok)
{
	int wincntr = winpoAftern - ((SPEEDPIV_WINLEN << 16) / 2);
	int rdidx = rdidx0 + n; if (rdidx > (winpoAftern >> 16)) rdidx -= SPEEDPIV_BUFLEN; if ((rdidx < (winpoAftern >> 16) - SPEEDPIV_BUFLEN)) rdidx += SPEEDPIV_BUFLEN;
	int alpha = (rdidx << 16) - wincntr;
	int nout = 0;
	int *sbm_buf_ptr = sbm_buf_left;
	int *out1ptr = out1;
	int bup_n = n;
	int alt_r = r;
	if(ssc_mono_sum_info == 1)
		sbm_buf_ptr = sbm_buf_right;
	if (signr*alpha > (DIST_THR_1 << 16))
	{
		if (Pitch_Ok)
		{
			if (Start_PitchCrossFade(Pg_0.Pitch, r))
			{
				Speed_Proc_State = SPEED_PROC_STATE_PROC_PITCH;
				return nout;
			}
			else
				Pitch_Ok = 0;
		}
	}

	wincntr = winpos - ((SPEEDPIV_WINLEN << 16) / 2);
	alpha = (rdidx0 << 16) - wincntr;/*CROSSFADE is applied for next frame*/
	if ((signr*alpha > (DIST_THR_2 << 16)) && (!Pitch_Ok) && (sbm_internal_count < buf_lvl_offset_prot))
	{
		Start_UnconstrainedCrossfade(r); Speed_Proc_State = SPEED_PROC_STATE_PROC_CROSSFADE;
		if (rdidx1 > (winpos >> 16)) rdidx1 -= SPEEDPIV_BUFLEN;     if ((rdidx1 < (winpos >> 16) - SPEEDPIV_BUFLEN)) rdidx1 += SPEEDPIV_BUFLEN;
		return nout;
	}
	if (transition_flag == EFFECT_TO_NORMAL)
	{
		alt_r = ONE_Q16; oFsz = n;
	}
	do {
		int d;
		// write next sample

		if (++wridx >= SPEEDPIV_BUFLEN)
			wridx = 0;

		d = wridx - (winpos >> 16);
		d = ((d + SPEEDPIV_BUFLEN + SPEEDPIV_BUFLEN / 2) % SPEEDPIV_BUFLEN) - SPEEDPIV_BUFLEN / 2;


		while (d > 0)
		{
			int dl;

			int wincntr = winpos - ((SPEEDPIV_WINLEN << 16) / 2);

			int alpha = (rdidx0 << 16) - wincntr;

			dl = sbm_buf_ptr[rdidx0];
			/*if (signr*alpha>(DIST_THR_1<<16))
			{
				if (Pitch_Ok) {if (Start_PitchCrossFade(Pg_0.Pitch,r)) Speed_Proc_State=SPEED_PROC_STATE_PROC_PITCH;}
			}
			if ((signr*alpha > (DIST_THR_2 << 16)) && (!Pitch_Ok))
			{
				Start_UnconstrainedCrossfade(r); Speed_Proc_State = SPEED_PROC_STATE_PROC_CROSSFADE;
			}*/

			*out1++ = dl;

			// debug
			//*out2++ = Pitch0 * (1<<(6+6));
			//*out2++ = Pg_0.Gain * (1<<(6+0));
			//*out2++ = pitchstabstate * (1 << (6 + 6));
		//*out2++ = (Pitch_Ok ? 16384 : 0) << 6;
		//*out2++ = ((int)Speed_Proc_State<<13) << 6;

			nout++;     // increment output sample number

			// increment window pointer
			winpos += alt_r;
			if (winpos >= (SPEEDPIV_BUFLEN << 16)) winpos -= (SPEEDPIV_BUFLEN << 16);

			++rdidx0;   if (rdidx0 > (winpos >> 16)) rdidx0 -= SPEEDPIV_BUFLEN;     if ((rdidx0 < (winpos >> 16) - SPEEDPIV_BUFLEN)) rdidx0 += SPEEDPIV_BUFLEN;
			++rdidx1;   if (rdidx1 > (winpos >> 16)) rdidx1 -= SPEEDPIV_BUFLEN;     if ((rdidx1 < (winpos >> 16) - SPEEDPIV_BUFLEN)) rdidx1 += SPEEDPIV_BUFLEN;

			d = wridx - (winpos >> 16);
			d = ((d + SPEEDPIV_BUFLEN + SPEEDPIV_BUFLEN / 2) % SPEEDPIV_BUFLEN) - SPEEDPIV_BUFLEN / 2;
		}   //   while (d > 0)

	} while (--n > 0);
	/*Protection code to make during effect to normal the framework expects output samples as NORMAL case*/
	if ((transition_flag == EFFECT_TO_NORMAL) && nout != bup_n)
	{
		nout = DecIntSamplesMono(out1ptr, bup_n, nout);
	}
	return nout;
}

 int Speed_Proc_State_PP_mono(int *out1, int n)
{
	int nout = 0;
	int *sbm_buf_ptr = sbm_buf_left;
	int *out1ptr = out1;
	int bup_n = n;
	if (ssc_mono_sum_info == 1)
		sbm_buf_ptr = sbm_buf_right;
	if (gain_crfade <= 1)
	{
		gain_crfade = 0; Stop_PitchCrossFade(); Speed_Proc_State = SPEED_PROC_STATE_NORMAL; pitch_prot_cnt = 0; return nout;
	}

	do {
		int d;
		// write next sample

		if (++wridx >= SPEEDPIV_BUFLEN)
			wridx = 0;

		d = wridx - (winpos >> 16);
		d = ((d + SPEEDPIV_BUFLEN + SPEEDPIV_BUFLEN / 2) % SPEEDPIV_BUFLEN) - SPEEDPIV_BUFLEN / 2;


		while (d > 0)
		{
			int dl;

			int wincntr = winpos - ((SPEEDPIV_WINLEN << 16) / 2);

			int alpha = (rdidx0 << 16) - wincntr;

			int mgain_crfade = (1 << 26) - gain_crfade;
			dl = (int)(((INT64)sbm_buf_ptr[rdidx0] * gain_crfade + (INT64)sbm_buf_ptr[rdidx1] * mgain_crfade + (1 << (26 - 1))) >> 26);
			gain_crfade -= delta_crfade;
			if (gain_crfade < 0) { gain_crfade = 1; }


			*out1++ = dl;

			// debug
			//*out2++ = Pitch0 * (1<<(6+6));
			//*out2++ = Pg_0.Gain * (1<<(6+0));
			//*out2++ = pitchstabstate * (1 << (6 + 6));
		//*out2++ = (Pitch_Ok ? 16384 : 0) << 6;
		//*out2++ = ((int)Speed_Proc_State<<13) << 6;

			nout++;     // increment output sample number

			// increment window pointer
			winpos += r;
			if (winpos >= (SPEEDPIV_BUFLEN << 16)) winpos -= (SPEEDPIV_BUFLEN << 16);

			++rdidx0;   if (rdidx0 > (winpos >> 16)) rdidx0 -= SPEEDPIV_BUFLEN;     if ((rdidx0 < (winpos >> 16) - SPEEDPIV_BUFLEN)) rdidx0 += SPEEDPIV_BUFLEN;
			++rdidx1;   if (rdidx1 > (winpos >> 16)) rdidx1 -= SPEEDPIV_BUFLEN;     if ((rdidx1 < (winpos >> 16) - SPEEDPIV_BUFLEN)) rdidx1 += SPEEDPIV_BUFLEN;

			d = wridx - (winpos >> 16);
			d = ((d + SPEEDPIV_BUFLEN + SPEEDPIV_BUFLEN / 2) % SPEEDPIV_BUFLEN) - SPEEDPIV_BUFLEN / 2;
		}

	} while (--n > 0);

	/*Protection code to make during effect to normal the framework expects output samples as NORMAL case*/
	if ((transition_flag == EFFECT_TO_NORMAL) && nout != bup_n)
	{
		nout = DecIntSamplesMono(out1ptr, bup_n, nout);
	}
	return nout;
}

 int Speed_Proc_State_PCF_mono(int *out1, int n)
{
	int nout = 0;
	int idx_alpha = 0;
	int idx_beta = 0;
	int *sbm_buf_ptr = sbm_buf_left;
	int *out1ptr = out1;
	int bup_n = n;
	if (ssc_mono_sum_info == 1)
		sbm_buf_ptr = sbm_buf_right;
	if (flagEnabled_CROSSFADE_Fin) {
		Stop_UnconstrainedCrossFade(); Speed_Proc_State = SPEED_PROC_STATE_NORMAL; flagEnabled_CROSSFADE_Fin = 0; return  Speed_Proc_State;
	}

	do {
		int d;
		// write next sample

		if (++wridx >= SPEEDPIV_BUFLEN)
			wridx = 0;

		d = wridx - (winpos >> 16);
		d = ((d + SPEEDPIV_BUFLEN + SPEEDPIV_BUFLEN / 2) % SPEEDPIV_BUFLEN) - SPEEDPIV_BUFLEN / 2;


		while (d > 0)
		{
			int dl;

			int wincntr = winpos - ((SPEEDPIV_WINLEN << 16) / 2);

			int alpha = (rdidx0 << 16) - wincntr;
			if (flagEnabled_CROSSFADE_Fin)
			{
				dl = sbm_buf_ptr[rdidx1];
			}
			else
			{
				alpha = ABS(alpha) - (DIST_THR_2 << 16);                 // alpha starts from 0
				idx_alpha = alpha >> (16 + 0);                  // integer part
				int gamma = alpha - (idx_alpha << (16 + 0));        // fractional part (Q(16+0))
				int gamma_m1 = (1 << (16 + 0)) - gamma;
				idx_alpha <<= 1;                                      // use prev table (2 times longer)
				alpha = (int)((((INT64)win[idx_alpha] * gamma_m1 + (INT64)win[idx_alpha + 1 * 2] * gamma)) >> (16 + 0));
				idx_beta = (SPEEDPIV_WINLEN / 2) - 1 * 2 - idx_alpha;
				int beta = (int)((((INT64)win[idx_beta] * gamma + (INT64)win[idx_beta + 1 * 2] * gamma_m1)) >> (16 + 0));
				dl = (int)(((INT64)sbm_buf_ptr[rdidx0] * beta + (INT64)sbm_buf_ptr[rdidx1] * alpha + (1 << (26 - 1))) >> 26);
				if (idx_beta <= 1) { flagEnabled_CROSSFADE_Fin = 1; }
			}
			//if (idx_beta<=1) { Stop_UnconstrainedCrossFade(); Speed_Proc_State = SPEED_PROC_STATE_NORMAL; }
			*out1++ = dl;

			// debug
			//*out2++ = Pitch0 * (1<<(6+6));
			//*out2++ = Pg_0.Gain * (1<<(6+0));
			//*out2++ = pitchstabstate * (1 << (6 + 6));
		//*out2++ = (Pitch_Ok ? 16384 : 0) << 6;
		//*out2++ = ((int)Speed_Proc_State<<13) << 6;

			nout++;     // increment output sample number

			// increment window pointer
			winpos += r;
			if (winpos >= (SPEEDPIV_BUFLEN << 16)) winpos -= (SPEEDPIV_BUFLEN << 16);

			++rdidx0;   if (rdidx0 > (winpos >> 16)) rdidx0 -= SPEEDPIV_BUFLEN;     if ((rdidx0 < (winpos >> 16) - SPEEDPIV_BUFLEN)) rdidx0 += SPEEDPIV_BUFLEN;
			++rdidx1;   if (rdidx1 > (winpos >> 16)) rdidx1 -= SPEEDPIV_BUFLEN;     if ((rdidx1 < (winpos >> 16) - SPEEDPIV_BUFLEN)) rdidx1 += SPEEDPIV_BUFLEN;

			d = wridx - (winpos >> 16);
			d = ((d + SPEEDPIV_BUFLEN + SPEEDPIV_BUFLEN / 2) % SPEEDPIV_BUFLEN) - SPEEDPIV_BUFLEN / 2;
		}   //   while (d > 0)

	} while (--n > 0);

	/*Protection code to make during effect to normal the framework expects output samples as NORMAL case*/
	if ((transition_flag == EFFECT_TO_NORMAL) && nout != bup_n)
	{
		nout = DecIntSamplesMono(out1ptr, bup_n, nout);
	}
	return nout;
}

 int SBM_Exe_Frame_Ch(int *out1, int *out2, int ch, int n)
{
	// debug (no pitch info)
// Pg_0.Pitch=Pg_m1.Pitch=0;

////// analyse current pitch status
// Pitch diff
	int PitchDiff_Ok = 0;
	// if jump is possible inside of frame
	if ((Pg_0.Pitch > COMBFILTER_MINPERIOD) && (Pg_0.Gain > PGAIN_THR))
		if (Pg_0.Pitch < (winpos >> 16) - rdidx0)
			PitchDiff_Ok = 1;
	// if jump to previous frame is possible (Pitch0 and Pitch1 have minor difference)
	if ((Pg_0.Pitch > COMBFILTER_MINPERIOD) && (Pg_m1.Pitch > COMBFILTER_MINPERIOD) &&
		(Pg_0.Gain > PGAIN_THR) && (Pg_m1.Gain > PGAIN_THR))
		if (ABS(Pg_0.Pitch - Pg_m1.Pitch) < ((Pg_0.Pitch*PITCHDIFFALPHA) >> QPITCH))
			PitchDiff_Ok = 1;

	// Pitch processing availability
	int Pitch_Ok = PitchDiff_Ok && PitchIsStable;


	int signr = (r > (1 << 16)) ? -1 : 1;
	if (r == (1 << 16)) signr = 0;

	int nout = 0;
	int winpoAftern = winpos + r * n;
	int idx_alpha = 0;
	int idx_beta = 0;
	//int n_bup = n;
	//Speed_Proc_State = SPEED_PROC_STATE_PROC_PITCH;
	//Pitch_Ok = 1;
#if 0
	if (Speed_Proc_State == SPEED_PROC_STATE_NORMAL)
		Speed_Proc_State = Speed_Proc_State_NML(out1, out2, n, winpoAftern, signr, Pitch_Ok);
	nout = Speed_Proc_State;
	if (Speed_Proc_State == SPEED_PROC_STATE_PROC_PITCH)
	{
		Speed_Proc_State = Speed_Proc_State_PP(out1, out2, n);
		nout = Speed_Proc_State;
		if (Speed_Proc_State == SPEED_PROC_STATE_NORMAL)
			nout = Speed_Proc_State_NML(out1, out2, n, winpoAftern, signr, Pitch_Ok);
	}
	if (Speed_Proc_State == SPEED_PROC_STATE_PROC_CROSSFADE)
	{
		Speed_Proc_State = Speed_Proc_State_PCF(out1, out2, n);
		nout = Speed_Proc_State;
		if (Speed_Proc_State == SPEED_PROC_STATE_NORMAL)
			nout = Speed_Proc_State_NML(out1, out2, n, winpoAftern, signr, Pitch_Ok);
}
#else
	//int u_Speed_Proc_State = Speed_Proc_State;
jmp_SPEED_PROC_STATE_NORMAL:
	if (Speed_Proc_State == SPEED_PROC_STATE_NORMAL)
	{
		if(ch == 2)
			nout = Speed_Proc_State_NML_stereo(out1, out2, n, winpoAftern, signr, Pitch_Ok);
		else
			nout = Speed_Proc_State_NML_mono(out1, n, winpoAftern, signr, Pitch_Ok);
	}
	if (Speed_Proc_State == SPEED_PROC_STATE_PROC_PITCH)
	{
		if (ch == 2)
			nout = Speed_Proc_State_PP_stereo(out1, out2, n);
		else
			nout = Speed_Proc_State_PP_mono(out1, n);

		if (Speed_Proc_State == SPEED_PROC_STATE_NORMAL)
			goto jmp_SPEED_PROC_STATE_NORMAL;
	}
	if (Speed_Proc_State == SPEED_PROC_STATE_PROC_CROSSFADE)
	{
		if (ch == 2)
			nout = Speed_Proc_State_PCF_stereo(out1, out2, n);
		else
			nout = Speed_Proc_State_PCF_mono(out1, n);

		if (Speed_Proc_State == SPEED_PROC_STATE_NORMAL)
			goto jmp_SPEED_PROC_STATE_NORMAL;
	}
#endif
	while (rdidx0 >= 0)
	{
		rdidx0 = rdidx0 - SPEEDPIV_BUFLEN;
	}

	while (rdidx1 >= 0)
	{
		rdidx1 = rdidx1 - SPEEDPIV_BUFLEN;
	}
	/*if(nout > n_bup)
		get_sbm_state_ret = */
	return nout;
}

