/*
 * Copyright 2018-2025 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <string.h>


#include "CircularBufManagement.h"



//--------------------------circular buffer management functions for s16 1ch, or S8 2ch --------------------- beg----
//--------------------------circular buffer management functions for s16 1ch, or S8 2ch --------------------- beg----
//--------------------------circular buffer management functions for s16 1ch, or S8 2ch --------------------- beg----
#if defined(EnableCirBufFunctionsForS16)&&(EnableCirBufFunctionsForS16==1)
//it is critical to understand that, DataAreaHead must points to a place with space >= (BufLen + MaxReadLen)
void InitCirAudioBuf_S16(volatile T_CircularAudioBuf_S16 *CirBufPtr,short int *DataAreaHead,unsigned int BufLen)
{
    CirBufPtr->PtrBufHead=DataAreaHead;
    CirBufPtr->LengthInSamples=BufLen;
    CirBufPtr->PtrRd=DataAreaHead;
    CirBufPtr->PtrWr=DataAreaHead;
}

//this function doesn't check if there are enough space available. Before calling this function, should call CirAudioBuf_SpaceAvailableInSamples_S16
void CirAudioBuf_WriteSamples_S16(volatile T_CircularAudioBuf_S16 *CirBufPtr, unsigned int SampleNumbersToBePut, short int *PtrAudioDataSrc)
{
	if ((CirBufPtr->LengthInSamples - (CirBufPtr->PtrWr - CirBufPtr->PtrBufHead) + 1) >= SampleNumbersToBePut)
	{   //no need to cut
		memcpy(CirBufPtr->PtrWr, PtrAudioDataSrc, SampleNumbersToBePut * sizeof(short int));

		if (CirBufPtr->PtrWr + SampleNumbersToBePut > CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
			CirBufPtr->PtrWr = CirBufPtr->PtrWr + SampleNumbersToBePut - CirBufPtr->LengthInSamples - 1;
		else
			CirBufPtr->PtrWr += SampleNumbersToBePut;
	} else
	{   //need to cut into 2 parts
		unsigned int l1;
		unsigned int l2;

		l1 = CirBufPtr->LengthInSamples - (CirBufPtr->PtrWr - CirBufPtr->PtrBufHead) + 1;
		l2 = SampleNumbersToBePut - l1;
		memcpy(CirBufPtr->PtrWr, PtrAudioDataSrc, l1 * sizeof(short int));

		PtrAudioDataSrc += l1;
		memcpy(CirBufPtr->PtrBufHead, PtrAudioDataSrc, l2 * sizeof(short int));
		CirBufPtr->PtrWr = CirBufPtr->PtrBufHead + l2;
	}
}

//this function doesn't check if there are enough samples available. Before calling this function, should call CirAudioBuf_SpaceOccupiedInSamples_S16
short int* CirAudioBuf_ReadSamples_GetRdPtr_S16(volatile T_CircularAudioBuf_S16 *CirBufPtr, unsigned int SampleNumbersToBeGot)
{
	short int *ptrR;
	//make it clear that: before calling this function, it must have been confirmed that there are enough data (>SampleNumbersToBeGot) available after the read pointer
	if ((CirBufPtr->LengthInSamples - (CirBufPtr->PtrRd - CirBufPtr->PtrBufHead) + 1) >= SampleNumbersToBeGot)
	{   //no need to cut
		ptrR = CirBufPtr->PtrRd;
		if (CirBufPtr->PtrRd + SampleNumbersToBeGot > CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
			CirBufPtr->PtrRd = CirBufPtr->PtrRd + SampleNumbersToBeGot - CirBufPtr->LengthInSamples - 1;
		else
			CirBufPtr->PtrRd += SampleNumbersToBeGot;
		return ptrR;
	} else
	{   //need to merge 2 parts together
	    unsigned int l1;
	    unsigned int l2;

		l1 = CirBufPtr->LengthInSamples - (CirBufPtr->PtrRd - CirBufPtr->PtrBufHead) + 1;
		l2 = SampleNumbersToBeGot - l1;
		memcpy(CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples + 1, CirBufPtr->PtrBufHead, l2 * sizeof(short int));
		ptrR = CirBufPtr->PtrRd;
		CirBufPtr->PtrRd = CirBufPtr->PtrBufHead + l2;
		return ptrR;
	}
}

unsigned int CirAudioBuf_SpaceOccupiedInSamples_S16(volatile T_CircularAudioBuf_S16 *CirBufPtr)
{
	//buf is completely empty
	if (CirBufPtr->PtrRd == CirBufPtr->PtrWr)
		return (0);

	if (CirBufPtr->PtrWr > CirBufPtr->PtrRd)
	{
		return (CirBufPtr->PtrWr - CirBufPtr->PtrRd);
	} else {
		return (CirBufPtr->LengthInSamples - (CirBufPtr->PtrRd - CirBufPtr->PtrWr) + 1);
	}
}
unsigned int CirAudioBuf_SpaceAvailableInSamples_S16(volatile T_CircularAudioBuf_S16 *CirBufPtr)
{
	if (CirBufPtr->PtrRd == CirBufPtr->PtrWr)
		return (CirBufPtr->LengthInSamples);

	if (CirBufPtr->PtrWr > CirBufPtr->PtrRd)
	{
		return (CirBufPtr->LengthInSamples - (CirBufPtr->PtrWr - CirBufPtr->PtrRd));
	} else
	{
		return ((CirBufPtr->PtrRd - CirBufPtr->PtrWr) - 1);
	}
}
void CirAudioBuf_ClearAllSamples_S16(volatile T_CircularAudioBuf_S16 *CirBufPtr)
{
	CirBufPtr->PtrRd = CirBufPtr->PtrBufHead;
	CirBufPtr->PtrWr = CirBufPtr->PtrBufHead;
}

//this function doesn't check if there are enough samples available. Before calling this function, should call CirAudioBuf_SpaceOccupiedInSamples_S16
void CirAudioBuf_ReadSamples_S16(volatile T_CircularAudioBuf_S16 *CirBufPtr, unsigned int SampleNumbersToBeGot, short int *PtrAudioDataDst)
{
	if ((CirBufPtr->LengthInSamples - (CirBufPtr->PtrRd - CirBufPtr->PtrBufHead) + 1) >= SampleNumbersToBeGot)
	{   //no need to cut
        memcpy(PtrAudioDataDst,CirBufPtr->PtrRd,SampleNumbersToBeGot*sizeof(short int));
		if (CirBufPtr->PtrRd + SampleNumbersToBeGot > CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
			CirBufPtr->PtrRd = CirBufPtr->PtrRd + SampleNumbersToBeGot - CirBufPtr->LengthInSamples - 1;
		else
			CirBufPtr->PtrRd += SampleNumbersToBeGot;
		return;
	} else
	{   //need to merge 2 parts together
	    unsigned int l1;
	    unsigned int l2;

		l1 = CirBufPtr->LengthInSamples - (CirBufPtr->PtrRd - CirBufPtr->PtrBufHead) + 1;
		l2 = SampleNumbersToBeGot - l1;

        memcpy(PtrAudioDataDst,CirBufPtr->PtrRd,     l1*sizeof(short int));
        PtrAudioDataDst+=l1;
        memcpy(PtrAudioDataDst,CirBufPtr->PtrBufHead,l2*sizeof(short int));
		CirBufPtr->PtrRd = CirBufPtr->PtrBufHead + l2;
		return;
	}
}

#if defined(EnableLessUsedCirBufFunctions)&&(EnableLessUsedCirBufFunctions==1)

unsigned char CirAudioBuf_GetUsagePercentage_S16(volatile T_CircularAudioBuf_S16 *CirBufPtr)
{
	unsigned int a, b;
	a = CirAudioBuf_SpaceOccupiedInSamples_S16(CirBufPtr);
	b = CirBufPtr->LengthInSamples;
	return (a * 100 / b);
}

void CirAudioBuf_MoveRdPtrForwards_S16(volatile T_CircularAudioBuf_S16 *CirBufPtr, unsigned int NumOfSamplesToGoForward)
{
	if ((CirBufPtr->PtrRd - NumOfSamplesToGoForward) >= CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
	{
		CirBufPtr->PtrRd += NumOfSamplesToGoForward;
		CirBufPtr->PtrRd -= CirBufPtr->LengthInSamples;
	} else
	{
		CirBufPtr->PtrRd += NumOfSamplesToGoForward;
	}
}
short int* CirAudioBuf_GetDdPtrForwards_S16(volatile T_CircularAudioBuf_S16 *CirBufPtr, unsigned int NumOfSamplesToGoForward)
{
	short int *p;
	if ((CirBufPtr->PtrRd - NumOfSamplesToGoForward) >= CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
	{
		p = CirBufPtr->PtrRd + NumOfSamplesToGoForward;
		p -= CirBufPtr->LengthInSamples;
	} else
	{
		p = CirBufPtr->PtrRd + NumOfSamplesToGoForward;
	}
	return(p);
}
void CirAudioBuf_MoveRdPtrBackwards_S16(volatile T_CircularAudioBuf_S16 *CirBufPtr, unsigned int NumOfSamplesToGoBack)
{
	if ((CirBufPtr->PtrRd - NumOfSamplesToGoBack) >= CirBufPtr->PtrBufHead)
	{
		CirBufPtr->PtrRd -= NumOfSamplesToGoBack;
	} else
	{
		CirBufPtr->PtrRd -= NumOfSamplesToGoBack;
		CirBufPtr->PtrRd += (CirBufPtr->LengthInSamples + 1);
	}
}
short int* CirAudioBuf_GetRdPtrBackwards_S16(volatile T_CircularAudioBuf_S16 *CirBufPtr, unsigned int NumOfSamplesToGoBack)
{
	short int *p;
	if ((CirBufPtr->PtrRd - NumOfSamplesToGoBack) >= CirBufPtr->PtrBufHead)
	{
		p=CirBufPtr->PtrRd - NumOfSamplesToGoBack;
	} else
	{
		p=CirBufPtr->PtrRd - NumOfSamplesToGoBack;
		p += (CirBufPtr->LengthInSamples + 1);
	}
	return(p);
}

void CirAudioBuf_MoveWrPtrForwards_S16(volatile T_CircularAudioBuf_S16 *CirBufPtr, unsigned int NumOfSamplesToGoForward)
{
	if ((CirBufPtr->PtrWr - NumOfSamplesToGoForward) >= CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
	{
		CirBufPtr->PtrWr += NumOfSamplesToGoForward;
		CirBufPtr->PtrWr -= CirBufPtr->LengthInSamples;
	} else
	{
		CirBufPtr->PtrWr += NumOfSamplesToGoForward;
	}
}
short int* CirAudioBuf_GetWrPtrForwards_S16(volatile T_CircularAudioBuf_S16 *CirBufPtr, unsigned int NumOfSamplesToGoForward)
{
	short int *p;
	if ((CirBufPtr->PtrWr - NumOfSamplesToGoForward) >= CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
	{
		p = CirBufPtr->PtrWr + NumOfSamplesToGoForward;
		p -= CirBufPtr->LengthInSamples;
	} else
	{
		p = CirBufPtr->PtrWr + NumOfSamplesToGoForward;
	}
	return(p);
}
void CirAudioBuf_MoveWrPtrBackwards_S16(volatile T_CircularAudioBuf_S16 *CirBufPtr, unsigned int NumOfSamplesToGoBack)
{
	if ((CirBufPtr->PtrWr - NumOfSamplesToGoBack) >= CirBufPtr->PtrBufHead)
	{
		CirBufPtr->PtrWr -= NumOfSamplesToGoBack;
	} else
	{
		CirBufPtr->PtrWr -= NumOfSamplesToGoBack;
		CirBufPtr->PtrWr += (CirBufPtr->LengthInSamples + 1);
	}
}
short int* CirAudioBuf_GetWrPtrBackwards_S16(volatile T_CircularAudioBuf_S16 *CirBufPtr, unsigned int NumOfSamplesToGoBack)
{
	short int *p;
	if ((CirBufPtr->PtrWr - NumOfSamplesToGoBack) >= CirBufPtr->PtrBufHead)
	{
		p=CirBufPtr->PtrWr - NumOfSamplesToGoBack;
	} else
	{
		p=CirBufPtr->PtrWr - NumOfSamplesToGoBack;
		p += (CirBufPtr->LengthInSamples + 1);
	}
	return(p);
}
#endif      //EnableLessUsedCirBufFunctions
#endif      //EnableCirBufFunctionsForS16
//--------------------------circular buffer management functions for s16 1ch, or S8 2ch --------------------- end----
//--------------------------circular buffer management functions for s16 1ch, or S8 2ch --------------------- end----
//--------------------------circular buffer management functions for s16 1ch, or S8 2ch --------------------- end----





//-------------------circular buffer management functions for int type, could be s16 2ch, or int 1ch -------- beg----
//-------------------circular buffer management functions for int type, could be s16 2ch, or int 1ch -------- beg----
//-------------------circular buffer management functions for int type, could be s16 2ch, or int 1ch -------- beg----
#if defined(EnableCirBufFunctionsForS32)&&(EnableCirBufFunctionsForS32==1)
//it is critical to understand that, DataAreaHead must points to a place with space >= (BufLen + MaxReadLen)
void InitCirAudioBuf_S32(volatile T_CircularAudioBuf_S32 *CirBufPtr,int *DataAreaHead,unsigned int BufLen)
{
    CirBufPtr->PtrBufHead=DataAreaHead;
    CirBufPtr->LengthInSamples=BufLen;
    CirBufPtr->PtrRd=DataAreaHead;
    CirBufPtr->PtrWr=DataAreaHead;
}

//this function doesn't check if there are enough space available. Before calling this function, should call CirAudioBuf_SpaceAvailableInSamples_S32
void CirAudioBuf_WriteSamples_S32(volatile T_CircularAudioBuf_S32 *CirBufPtr, unsigned int SampleNumbersToBePut, int *PtrAudioDataSrc)
{
	if ((CirBufPtr->LengthInSamples - (CirBufPtr->PtrWr - CirBufPtr->PtrBufHead) + 1) >= SampleNumbersToBePut)
	{   //no need to cut
		memcpy(CirBufPtr->PtrWr, PtrAudioDataSrc, SampleNumbersToBePut * sizeof(int));

		if (CirBufPtr->PtrWr + SampleNumbersToBePut > CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
			CirBufPtr->PtrWr = CirBufPtr->PtrWr + SampleNumbersToBePut - CirBufPtr->LengthInSamples - 1;
		else
			CirBufPtr->PtrWr += SampleNumbersToBePut;
	} else
	{   //need to cut into 2 parts
		unsigned int l1;
		unsigned int l2;

		l1 = CirBufPtr->LengthInSamples - (CirBufPtr->PtrWr - CirBufPtr->PtrBufHead) + 1;
		l2 = SampleNumbersToBePut - l1;
		memcpy(CirBufPtr->PtrWr, PtrAudioDataSrc, l1 * sizeof(int));

		PtrAudioDataSrc += l1;
		memcpy(CirBufPtr->PtrBufHead, PtrAudioDataSrc, l2 * sizeof(int));
		CirBufPtr->PtrWr = CirBufPtr->PtrBufHead + l2;
	}
}

//this function doesn't check if there are enough samples available. Before calling this function, should call CirAudioBuf_SpaceOccupiedInSamples_S32
int* CirAudioBuf_ReadSamples_GetRdPtr_S32(volatile T_CircularAudioBuf_S32 *CirBufPtr, unsigned int SampleNumbersToBeGot)
{
	int *ptrR;
	//make it clear that: before calling this function, it must have been confirmed that there are enough data (>SampleNumbersToBeGot) available after the read pointer
	if ((CirBufPtr->LengthInSamples - (CirBufPtr->PtrRd - CirBufPtr->PtrBufHead) + 1) >= SampleNumbersToBeGot)
	{   //no need to cut
		ptrR = CirBufPtr->PtrRd;
		if (CirBufPtr->PtrRd + SampleNumbersToBeGot > CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
			CirBufPtr->PtrRd = CirBufPtr->PtrRd + SampleNumbersToBeGot - CirBufPtr->LengthInSamples - 1;
		else
			CirBufPtr->PtrRd += SampleNumbersToBeGot;
		return ptrR;
	} else
	{   //need to merge 2 parts together
	    unsigned int l1;
	    unsigned int l2;

		l1 = CirBufPtr->LengthInSamples - (CirBufPtr->PtrRd - CirBufPtr->PtrBufHead) + 1;
		l2 = SampleNumbersToBeGot - l1;
		memcpy(CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples + 1, CirBufPtr->PtrBufHead, l2 * sizeof(int));
		ptrR = CirBufPtr->PtrRd;
		CirBufPtr->PtrRd = CirBufPtr->PtrBufHead + l2;
		return ptrR;
	}
}

unsigned int CirAudioBuf_SpaceOccupiedInSamples_S32(volatile T_CircularAudioBuf_S32 *CirBufPtr)
{
	//buf is completely empty
	if (CirBufPtr->PtrRd == CirBufPtr->PtrWr)
		return (0);

	if (CirBufPtr->PtrWr > CirBufPtr->PtrRd)
	{
		return (CirBufPtr->PtrWr - CirBufPtr->PtrRd);
	} else {
		return (CirBufPtr->LengthInSamples - (CirBufPtr->PtrRd - CirBufPtr->PtrWr) + 1);
	}
}
unsigned int CirAudioBuf_SpaceAvailableInSamples_S32(volatile T_CircularAudioBuf_S32 *CirBufPtr)
{
	if (CirBufPtr->PtrRd == CirBufPtr->PtrWr)
		return (CirBufPtr->LengthInSamples);

	if (CirBufPtr->PtrWr > CirBufPtr->PtrRd)
	{
		return (CirBufPtr->LengthInSamples - (CirBufPtr->PtrWr - CirBufPtr->PtrRd));
	} else
	{
		return ((CirBufPtr->PtrRd - CirBufPtr->PtrWr) - 1);
	}
}
void CirAudioBuf_ClearAllSamples_S32(volatile T_CircularAudioBuf_S32 *CirBufPtr)
{
	CirBufPtr->PtrRd = CirBufPtr->PtrBufHead;
	CirBufPtr->PtrWr = CirBufPtr->PtrBufHead;
}

//this function doesn't check if there are enough samples available. Before calling this function, should call CirAudioBuf_SpaceOccupiedInSamples_S32
void CirAudioBuf_ReadSamples_S32(volatile T_CircularAudioBuf_S32 *CirBufPtr, unsigned int SampleNumbersToBeGot, int *PtrAudioDataDst)
{
	if ((CirBufPtr->LengthInSamples - (CirBufPtr->PtrRd - CirBufPtr->PtrBufHead) + 1) >= SampleNumbersToBeGot)
	{   //no need to cut
        memcpy(PtrAudioDataDst,CirBufPtr->PtrRd,SampleNumbersToBeGot*sizeof(int));
		if (CirBufPtr->PtrRd + SampleNumbersToBeGot > CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
			CirBufPtr->PtrRd = CirBufPtr->PtrRd + SampleNumbersToBeGot - CirBufPtr->LengthInSamples - 1;
		else
			CirBufPtr->PtrRd += SampleNumbersToBeGot;
		return;
	} else
	{   //need to merge 2 parts together
	    unsigned int l1;
	    unsigned int l2;

		l1 = CirBufPtr->LengthInSamples - (CirBufPtr->PtrRd - CirBufPtr->PtrBufHead) + 1;
		l2 = SampleNumbersToBeGot - l1;

        memcpy(PtrAudioDataDst,CirBufPtr->PtrRd,     l1*sizeof(int));
        PtrAudioDataDst+=l1;
        memcpy(PtrAudioDataDst,CirBufPtr->PtrBufHead,l2*sizeof(int));
		CirBufPtr->PtrRd = CirBufPtr->PtrBufHead + l2;
		return;
	}
}

#if defined(EnableLessUsedCirBufFunctions)&&(EnableLessUsedCirBufFunctions==1)
unsigned char CirAudioBuf_GetUsagePercentage_S32(volatile T_CircularAudioBuf_S32 *CirBufPtr)
{
	unsigned int a, b;
	a = CirAudioBuf_SpaceOccupiedInSamples_S32(CirBufPtr);
	b = CirBufPtr->LengthInSamples;
	return (a * 100 / b);
}

void CirAudioBuf_MoveRdPtrForwards_S32(volatile T_CircularAudioBuf_S32 *CirBufPtr, unsigned int NumOfSamplesToGoForward)
{
	if ((CirBufPtr->PtrRd - NumOfSamplesToGoForward) >= CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
	{
		CirBufPtr->PtrRd += NumOfSamplesToGoForward;
		CirBufPtr->PtrRd -= CirBufPtr->LengthInSamples;
	} else
	{
		CirBufPtr->PtrRd += NumOfSamplesToGoForward;
	}
}
int* CirAudioBuf_GetDdPtrForwards_S32(volatile T_CircularAudioBuf_S32 *CirBufPtr, unsigned int NumOfSamplesToGoForward)
{
	int *p;
	if ((CirBufPtr->PtrRd - NumOfSamplesToGoForward) >= CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
	{
		p = CirBufPtr->PtrRd + NumOfSamplesToGoForward;
		p -= CirBufPtr->LengthInSamples;
	} else
	{
		p = CirBufPtr->PtrRd + NumOfSamplesToGoForward;
	}
	return(p);
}
void CirAudioBuf_MoveRdPtrBackwards_S32(volatile T_CircularAudioBuf_S32 *CirBufPtr, unsigned int NumOfSamplesToGoBack)
{
	if ((CirBufPtr->PtrRd - NumOfSamplesToGoBack) >= CirBufPtr->PtrBufHead)
	{
		CirBufPtr->PtrRd -= NumOfSamplesToGoBack;
	} else
	{
		CirBufPtr->PtrRd -= NumOfSamplesToGoBack;
		CirBufPtr->PtrRd += (CirBufPtr->LengthInSamples + 1);
	}
}
int* CirAudioBuf_GetRdPtrBackwards_S32(volatile T_CircularAudioBuf_S32 *CirBufPtr, unsigned int NumOfSamplesToGoBack)
{
	int *p;
	if ((CirBufPtr->PtrRd - NumOfSamplesToGoBack) >= CirBufPtr->PtrBufHead)
	{
		p=CirBufPtr->PtrRd - NumOfSamplesToGoBack;
	} else
	{
		p=CirBufPtr->PtrRd - NumOfSamplesToGoBack;
		p += (CirBufPtr->LengthInSamples + 1);
	}
	return(p);
}

void CirAudioBuf_MoveWrPtrForwards_S32(volatile T_CircularAudioBuf_S32 *CirBufPtr, unsigned int NumOfSamplesToGoForward)
{
	if ((CirBufPtr->PtrWr - NumOfSamplesToGoForward) >= CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
	{
		CirBufPtr->PtrWr += NumOfSamplesToGoForward;
		CirBufPtr->PtrWr -= CirBufPtr->LengthInSamples;
	} else
	{
		CirBufPtr->PtrWr += NumOfSamplesToGoForward;
	}
}
int* CirAudioBuf_GetWrPtrForwards_S32(volatile T_CircularAudioBuf_S32 *CirBufPtr, unsigned int NumOfSamplesToGoForward)
{
	int *p;
	if ((CirBufPtr->PtrWr - NumOfSamplesToGoForward) >= CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
	{
		p = CirBufPtr->PtrWr + NumOfSamplesToGoForward;
		p -= CirBufPtr->LengthInSamples;
	} else
	{
		p = CirBufPtr->PtrWr + NumOfSamplesToGoForward;
	}
	return(p);
}
void CirAudioBuf_MoveWrPtrBackwards_S32(volatile T_CircularAudioBuf_S32 *CirBufPtr, unsigned int NumOfSamplesToGoBack)
{
	if ((CirBufPtr->PtrWr - NumOfSamplesToGoBack) >= CirBufPtr->PtrBufHead)
	{
		CirBufPtr->PtrWr -= NumOfSamplesToGoBack;
	} else
	{
		CirBufPtr->PtrWr -= NumOfSamplesToGoBack;
		CirBufPtr->PtrWr += (CirBufPtr->LengthInSamples + 1);
	}
}
int* CirAudioBuf_GetWrPtrBackwards_S32(volatile T_CircularAudioBuf_S32 *CirBufPtr, unsigned int NumOfSamplesToGoBack)
{
	int *p;
	if ((CirBufPtr->PtrWr - NumOfSamplesToGoBack) >= CirBufPtr->PtrBufHead)
	{
		p=CirBufPtr->PtrWr - NumOfSamplesToGoBack;
	} else
	{
		p=CirBufPtr->PtrWr - NumOfSamplesToGoBack;
		p += (CirBufPtr->LengthInSamples + 1);
	}
	return(p);
}
#endif      //EnableLessUsedCirBufFunctions
#endif      //EnableCirBufFunctionsForS32
//-------------------circular buffer management functions for int type, could be s16 2ch, or int 1ch -------- end----
//-------------------circular buffer management functions for int type, could be s16 2ch, or int 1ch -------- end----
//-------------------circular buffer management functions for int type, could be s16 2ch, or int 1ch -------- end----





//------------------------circular buffer management functions for s64 1ch, or int 2ch --------------------- beg----
//------------------------circular buffer management functions for s64 1ch, or int 2ch --------------------- beg----
//------------------------circular buffer management functions for s64 1ch, or int 2ch --------------------- beg----
#if defined(EnableCirBufFunctionsForS64)&&(EnableCirBufFunctionsForS64==1)
//it is critical to understand that, DataAreaHead must points to a place with space >= (BufLen + MaxReadLen)
void InitCirAudioBuf_S64(volatile T_CircularAudioBuf_S64 *CirBufPtr,S64 *DataAreaHead,unsigned int BufLen)
{
    CirBufPtr->PtrBufHead=DataAreaHead;
    CirBufPtr->LengthInSamples=BufLen;
    CirBufPtr->PtrRd=DataAreaHead;
    CirBufPtr->PtrWr=DataAreaHead;
}

//this function doesn't check if there are enough space available. Before calling this function, should call CirAudioBuf_SpaceAvailableInSamples_S64
void CirAudioBuf_WriteSamples_S64(volatile T_CircularAudioBuf_S64 *CirBufPtr, unsigned int SampleNumbersToBePut, S64 *PtrAudioDataSrc)
{
	if ((CirBufPtr->LengthInSamples - (CirBufPtr->PtrWr - CirBufPtr->PtrBufHead) + 1) >= SampleNumbersToBePut)
	{   //no need to cut
		memcpy(CirBufPtr->PtrWr, PtrAudioDataSrc, SampleNumbersToBePut * sizeof(S64));

		if (CirBufPtr->PtrWr + SampleNumbersToBePut > CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
			CirBufPtr->PtrWr = CirBufPtr->PtrWr + SampleNumbersToBePut - CirBufPtr->LengthInSamples - 1;
		else
			CirBufPtr->PtrWr += SampleNumbersToBePut;
	} else
	{   //need to cut into 2 parts
		unsigned int l1;
		unsigned int l2;

		l1 = CirBufPtr->LengthInSamples - (CirBufPtr->PtrWr - CirBufPtr->PtrBufHead) + 1;
		l2 = SampleNumbersToBePut - l1;
		memcpy(CirBufPtr->PtrWr, PtrAudioDataSrc, l1 * sizeof(S64));

		PtrAudioDataSrc += l1;
		memcpy(CirBufPtr->PtrBufHead, PtrAudioDataSrc, l2 * sizeof(S64));
		CirBufPtr->PtrWr = CirBufPtr->PtrBufHead + l2;
	}
}

//this function doesn't check if there are enough samples available. Before calling this function, should call CirAudioBuf_SpaceOccupiedInSamples_S64
S64* CirAudioBuf_ReadSamples_GetRdPtr_S64(volatile T_CircularAudioBuf_S64 *CirBufPtr, unsigned int SampleNumbersToBeGot)
{
	S64 *ptrR;
	//make it clear that: before calling this function, it must have been confirmed that there are enough data (>SampleNumbersToBeGot) available after the read pointer
	if ((CirBufPtr->LengthInSamples - (CirBufPtr->PtrRd - CirBufPtr->PtrBufHead) + 1) >= SampleNumbersToBeGot)
	{   //no need to cut
		ptrR = CirBufPtr->PtrRd;
		if (CirBufPtr->PtrRd + SampleNumbersToBeGot > CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
			CirBufPtr->PtrRd = CirBufPtr->PtrRd + SampleNumbersToBeGot - CirBufPtr->LengthInSamples - 1;
		else
			CirBufPtr->PtrRd += SampleNumbersToBeGot;
		return ptrR;
	} else
	{   //need to merge 2 parts together
	    unsigned int l1;
	    unsigned int l2;

		l1 = CirBufPtr->LengthInSamples - (CirBufPtr->PtrRd - CirBufPtr->PtrBufHead) + 1;
		l2 = SampleNumbersToBeGot - l1;
		memcpy(CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples + 1, CirBufPtr->PtrBufHead, l2 * sizeof(S64));
		ptrR = CirBufPtr->PtrRd;
		CirBufPtr->PtrRd = CirBufPtr->PtrBufHead + l2;
		return ptrR;
	}
}

unsigned int CirAudioBuf_SpaceOccupiedInSamples_S64(volatile T_CircularAudioBuf_S64 *CirBufPtr)
{
	//buf is completely empty
	if (CirBufPtr->PtrRd == CirBufPtr->PtrWr)
		return (0);

	if (CirBufPtr->PtrWr > CirBufPtr->PtrRd)
	{
		return (CirBufPtr->PtrWr - CirBufPtr->PtrRd);
	} else {
		return (CirBufPtr->LengthInSamples - (CirBufPtr->PtrRd - CirBufPtr->PtrWr) + 1);
	}
}
unsigned int CirAudioBuf_SpaceAvailableInSamples_S64(volatile T_CircularAudioBuf_S64 *CirBufPtr)
{
	if (CirBufPtr->PtrRd == CirBufPtr->PtrWr)
		return (CirBufPtr->LengthInSamples);

	if (CirBufPtr->PtrWr > CirBufPtr->PtrRd)
	{
		return (CirBufPtr->LengthInSamples - (CirBufPtr->PtrWr - CirBufPtr->PtrRd));
	} else
	{
		return ((CirBufPtr->PtrRd - CirBufPtr->PtrWr) - 1);
	}
}
void CirAudioBuf_ClearAllSamples_S64(volatile T_CircularAudioBuf_S64 *CirBufPtr)
{
	CirBufPtr->PtrRd = CirBufPtr->PtrBufHead;
	CirBufPtr->PtrWr = CirBufPtr->PtrBufHead;
}

#if defined(EnableLessUsedCirBufFunctions)&&(EnableLessUsedCirBufFunctions==1)
//this function doesn't check if there are enough samples available. Before calling this function, should call CirAudioBuf_SpaceOccupiedInSamples_S64
void CirAudioBuf_ReadSamples_S64(volatile T_CircularAudioBuf_S64 *CirBufPtr, unsigned int SampleNumbersToBeGot, S64 *PtrAudioDataDst)
{
	if ((CirBufPtr->LengthInSamples - (CirBufPtr->PtrRd - CirBufPtr->PtrBufHead) + 1) >= SampleNumbersToBeGot)
	{   //no need to cut
        memcpy(PtrAudioDataDst,CirBufPtr->PtrRd,SampleNumbersToBeGot*sizeof(S64));
		if (CirBufPtr->PtrRd + SampleNumbersToBeGot > CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
			CirBufPtr->PtrRd = CirBufPtr->PtrRd + SampleNumbersToBeGot - CirBufPtr->LengthInSamples - 1;
		else
			CirBufPtr->PtrRd += SampleNumbersToBeGot;
		return;
	} else
	{   //need to merge 2 parts together
	    unsigned int l1;
	    unsigned int l2;

		l1 = CirBufPtr->LengthInSamples - (CirBufPtr->PtrRd - CirBufPtr->PtrBufHead) + 1;
		l2 = SampleNumbersToBeGot - l1;

        memcpy(PtrAudioDataDst,CirBufPtr->PtrRd,     l1*sizeof(S64));
        PtrAudioDataDst+=l1;
        memcpy(PtrAudioDataDst,CirBufPtr->PtrBufHead,l2*sizeof(S64));
		CirBufPtr->PtrRd = CirBufPtr->PtrBufHead + l2;
		return;
	}
}

unsigned char CirAudioBuf_GetUsagePercentage_S64(volatile T_CircularAudioBuf_S64 *CirBufPtr)
{
	unsigned int a, b;
	a = CirAudioBuf_SpaceOccupiedInSamples_S64(CirBufPtr);
	b = CirBufPtr->LengthInSamples;
	return (a * 100 / b);
}

void CirAudioBuf_MoveRdPtrForwards_S64(volatile T_CircularAudioBuf_S64 *CirBufPtr, unsigned int NumOfSamplesToGoForward)
{
	if ((CirBufPtr->PtrRd - NumOfSamplesToGoForward) >= CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
	{
		CirBufPtr->PtrRd += NumOfSamplesToGoForward;
		CirBufPtr->PtrRd -= CirBufPtr->LengthInSamples;
	} else
	{
		CirBufPtr->PtrRd += NumOfSamplesToGoForward;
	}
}
S64* CirAudioBuf_GetDdPtrForwards_S64(volatile T_CircularAudioBuf_S64 *CirBufPtr, unsigned int NumOfSamplesToGoForward)
{
	S64 *p;
	if ((CirBufPtr->PtrRd - NumOfSamplesToGoForward) >= CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
	{
		p = CirBufPtr->PtrRd + NumOfSamplesToGoForward;
		p -= CirBufPtr->LengthInSamples;
	} else
	{
		p = CirBufPtr->PtrRd + NumOfSamplesToGoForward;
	}
	return(p);
}
void CirAudioBuf_MoveRdPtrBackwards_S64(volatile T_CircularAudioBuf_S64 *CirBufPtr, unsigned int NumOfSamplesToGoBack)
{
	if ((CirBufPtr->PtrRd - NumOfSamplesToGoBack) >= CirBufPtr->PtrBufHead)
	{
		CirBufPtr->PtrRd -= NumOfSamplesToGoBack;
	} else
	{
		CirBufPtr->PtrRd -= NumOfSamplesToGoBack;
		CirBufPtr->PtrRd += (CirBufPtr->LengthInSamples + 1);
	}
}
S64* CirAudioBuf_GetRdPtrBackwards_S64(volatile T_CircularAudioBuf_S64 *CirBufPtr, unsigned int NumOfSamplesToGoBack)
{
	S64 *p;
	if ((CirBufPtr->PtrRd - NumOfSamplesToGoBack) >= CirBufPtr->PtrBufHead)
	{
		p=CirBufPtr->PtrRd - NumOfSamplesToGoBack;
	} else
	{
		p=CirBufPtr->PtrRd - NumOfSamplesToGoBack;
		p += (CirBufPtr->LengthInSamples + 1);
	}
	return(p);
}

void CirAudioBuf_MoveWrPtrForwards_S64(volatile T_CircularAudioBuf_S64 *CirBufPtr, unsigned int NumOfSamplesToGoForward)
{
	if ((CirBufPtr->PtrWr - NumOfSamplesToGoForward) >= CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
	{
		CirBufPtr->PtrWr += NumOfSamplesToGoForward;
		CirBufPtr->PtrWr -= CirBufPtr->LengthInSamples;
	} else
	{
		CirBufPtr->PtrWr += NumOfSamplesToGoForward;
	}
}
S64* CirAudioBuf_GetWrPtrForwards_S64(volatile T_CircularAudioBuf_S64 *CirBufPtr, unsigned int NumOfSamplesToGoForward)
{
	S64 *p;
	if ((CirBufPtr->PtrWr - NumOfSamplesToGoForward) >= CirBufPtr->PtrBufHead + CirBufPtr->LengthInSamples)
	{
		p = CirBufPtr->PtrWr + NumOfSamplesToGoForward;
		p -= CirBufPtr->LengthInSamples;
	} else
	{
		p = CirBufPtr->PtrWr + NumOfSamplesToGoForward;
	}
	return(p);
}
void CirAudioBuf_MoveWrPtrBackwards_S64(volatile T_CircularAudioBuf_S64 *CirBufPtr, unsigned int NumOfSamplesToGoBack)
{
	if ((CirBufPtr->PtrWr - NumOfSamplesToGoBack) >= CirBufPtr->PtrBufHead)
	{
		CirBufPtr->PtrWr -= NumOfSamplesToGoBack;
	} else
	{
		CirBufPtr->PtrWr -= NumOfSamplesToGoBack;
		CirBufPtr->PtrWr += (CirBufPtr->LengthInSamples + 1);
	}
}
S64* CirAudioBuf_GetWrPtrBackwards_S64(volatile T_CircularAudioBuf_S64 *CirBufPtr, unsigned int NumOfSamplesToGoBack)
{
	S64 *p;
	if ((CirBufPtr->PtrWr - NumOfSamplesToGoBack) >= CirBufPtr->PtrBufHead)
	{
		p=CirBufPtr->PtrWr - NumOfSamplesToGoBack;
	} else
	{
		p=CirBufPtr->PtrWr - NumOfSamplesToGoBack;
		p += (CirBufPtr->LengthInSamples + 1);
	}
	return(p);
}
#endif      //EnableLessUsedCirBufFunctions
#endif      //EnableCirBufFunctionsForS64
//------------------------circular buffer management functions for s64 1ch, or int 2ch --------------------- end----
//------------------------circular buffer management functions for s64 1ch, or int 2ch --------------------- end----
//------------------------circular buffer management functions for s64 1ch, or int 2ch --------------------- end----



