/*/==============================================================================================
//							FICHIER D'IMPLEMENTATION DU MODULE DE TRAITEMENT DE L'"ADPCM"
//
//		Créer	  :	03 / 12 / 97
//		Fichier	  :	StreamApm.cxx
//		Auteur	  :	Nicolas Meyer
//
//		Descriptif:	Sources des fonctions privées , qui gère le streaming. Ce fichier
//					n'est qu'une extension du fichier "Adpcm.cxx"
//
//==============================================================================================*/

static char		chBufferStrm[ 60000 ];		// Allocation d'un gros buffer de streaming (60 Ko)
/*********************************************************************************************************
// DEFINITION DE FONCTIONS

*/
unsigned long			fn_ulOpenStreamADPCM( char* pchFilename, lpSND_tdstADPCMVoice pstVoice, lpSND_tdstWAVEFORMATEX* ppstwfx );
unsigned long			fn_ulCloseStreamADPCM( lpSND_tdstADPCMVoice pstVoice );
unsigned long			fn_ulLoadSampleADPCM( unsigned long ulNbSample, lpSND_tdstADPCMVoice pstVoice );

/*********************************************************************************************************
unsigned long fn_ulOpenStreamADPCM( char* pchFilename, lpSND_tdstADPCMVoice pstVoice, lpSND_tdstWAVEFORMATEX* ppstwfx )

Paramètres
	Entrée:	- char*						pchFilename	Nom du fichier à streamer

	Sortie:	- lpSND_tdstADPCMVoice		pstVoice	Pointeur sur la voie de streaming
			- lpSND_tdstWAVEFORMATEX*	ppstwfx		Pointeur de pointeur sur l'en-tête de fichier

Valeur retournée:
			- unsigned long						Code d'erreur

Description:
	Ouverture d'un fichier en streaming. Remplie quelques champs tels que:
		- pstVoice->pchBeginDatas
		- pstVoice->pchCurrentDatas

*/
unsigned long fn_ulOpenStreamADPCM( char* pchFilename, lpSND_tdstADPCMVoice pstVoice, lpSND_tdstWAVEFORMATEX* ppstwfx )
{
	static SND_tdstWAVEFORMATEX	stwfx;
	char						chPathName[ 256 ];
	unsigned long				ulCode;
	long						lOffset;

	//une ressource doit absolument avoir été associée à la voie 
	snd_assert(pstVoice->uRefRes.pstPtr);

    SND_fn_vResolveFileName( pchFilename, chPathName );
	pstVoice->phFile	=	SND_fn_hOpenFileReadSnd( chPathName );
	if( pstVoice->phFile == OPENFILESND_FAILED ) {
//		pstVoice->phFile	=	NULL;	A ne pas faire, un handle nul pourrait être un paramètre valide
		SND_fn_vDisplayError(E_uwSndCannotOpenFile,chPathName);
		return ADPCM_OPENFILEFAILED;
	}

	//indexation sur le 1° bytes utile du MEGAFILE
	if (pstVoice->uRefRes.pstPtr!=NULL)
		lOffset=pstVoice->uRefRes.pstPtr->uRes.stSample.uData.stStream.ulOffsetFirst;
	else
		lOffset=0;
	SND_fn_dwSeekFileSnd( pstVoice->phFile, lOffset, SEEKFILESND_BEGIN );

	SND_fn_dwReadFileSnd( pstVoice->phFile, sizeof(SND_tdstWAVEFORMATEX), & stwfx );
	memcpy( & pstVoice->uLoop, & stwfx.uLoop, sizeof(tduState) );
	ulCode				=	fn_ulResolveVersion( stwfx.ulCompressId );
	if( ulCode != ADPCM_NOERROR )
		return ulCode;
// Pour l'initialisation des datas streamées il faut les 8 premiers octets du fichier
	SND_fn_dwReadFileSnd( pstVoice->phFile, 8, (char*)chBufferStrm );
	SND_fn_dwSeekFileSnd( pstVoice->phFile, (unsigned long)( -8 ), SEEKFILESND_CURRENT );

	pstVoice->pchBeginDatas		=	(char*)chBufferStrm;
	pstVoice->pchCurrentDatas	=	(char*)chBufferStrm;
// Il est normal que "pstVoice->pchEndDatas" ne soit pas allouer
	*ppstwfx					=	& stwfx;
	return ADPCM_NOERROR;
}

/*********************************************************************************************************
unsigned long fn_ulCloseStreamADPCM( lpSND_tdstADPCMVoice pstVoice )

Paramètres
	Entrée:	- lpSND_tdstADPCMVoice	pstVoice	Pointeur sur la voie de stream

	Sortie:	- NEANT

Valeur retournée:
			- unsigned long						Code d'erreur

Description:
	Fermeture d'un streaming

*/
unsigned long fn_ulCloseStreamADPCM( lpSND_tdstADPCMVoice pstVoice )
{
	if( pstVoice->phFile != OPENFILESND_FAILED )	{
		SND_fn_vCloseFileSnd( pstVoice->phFile );
		pstVoice->phFile	=	OPENFILESND_FAILED;
		return ADPCM_NOERROR;
	}
	return ADPCM_INVALIDPARAM;
}

/*********************************************************************************************************
unsigned long fn_ulLoadSampleADPCM( unsigned long ulNbSample, lpSND_tdstADPCMVoice pstVoice )

Paramètres
	Entrée:	- unsigned long			ulNbSample	Nombre de sample à rafraichir
			- lpSND_tdstADPCMVoice	pstVoice	Pointeur sur la voie de stream

	Sortie:	- lpSND_tdstADPCMVoice	pstVoice	Pointeur sur la voie de stream

Valeur retournée:
			- unsigned long						Code d'erreur

Description:
	Fermeture d'un streaming

*/
unsigned long fn_ulLoadSampleADPCM( unsigned long ulNbSample, lpSND_tdstADPCMVoice pstVoice )
{
	unsigned long	ulNbBytes;
	unsigned long	ulRead;
	long			lOffset;

	// Si un nombre impair de sample ont déjà été chargé il faut charger un échantillon de moins
	if( pstVoice->ulSamplePos % 2 )
		ulNbSample--;
	//indexation sur les samples
	if( pstVoice->unChannels == 1 ) {
		ulNbBytes	=	( ulNbSample >> 1 ) + ( ulNbSample % 2 );
		lOffset		=	( pstVoice->ulSampleStart >> 1 ) + pstVoice->ulSampleStart % 2;
	}
	else {
		ulNbBytes	=	ulNbSample + ( ulNbSample % 2 );
		lOffset		=	pstVoice->ulSampleStart;
	}
	//indexation sur le 1° bytes utile du MEGAFILE
	if (pstVoice->uRefRes.pstPtr!=NULL)
		lOffset+=pstVoice->uRefRes.pstPtr->uRes.stSample.uData.stStream.ulOffsetFirst;
// Translation du buffer de stream
	if( pstVoice->pchCurrentDatas - pstVoice->pchBeginDatas == lOffset ) {
// Nous sommes à la fin, cas d'un loopant
		//header de l'APM
		lOffset+=sizeof(SND_tdstWAVEFORMATEX);

		SND_fn_dwSeekFileSnd( pstVoice->phFile, lOffset , SEEKFILESND_BEGIN );	// SEEKFILESND_CURRENT
		pstVoice->pchBeginDatas		=	(char*)chBufferStrm - (unsigned long)( pstVoice->pchCurrentDatas - pstVoice->pchBeginDatas );
		pstVoice->pchCurrentDatas	=	(char*)chBufferStrm;
		pstVoice->pchEndDatas		=	pstVoice->pchBeginDatas + (unsigned long)( pstVoice->ulNbSample >> ( 2 - pstVoice->unChannels ) );
	}
	if( ulNbSample ) {
// Cas d'une lecture normale
		ulRead		=	SND_fn_dwReadFileSnd( pstVoice->phFile, ulNbBytes, (char*)chBufferStrm );
		pstVoice->pchBeginDatas		=	(char*)chBufferStrm - (unsigned long)( pstVoice->pchCurrentDatas - pstVoice->pchBeginDatas );
		pstVoice->pchEndDatas		=	(char*)chBufferStrm + (unsigned long)( pstVoice->pchEndDatas - pstVoice->pchCurrentDatas );
		pstVoice->pchCurrentDatas	=	(char*)chBufferStrm;
	}
	return ADPCM_NOERROR;
}
