/*
//////////////////////////////////////////////////////////////
//	SNDXD.C													//
//////////////////////////////////////////////////////////////
//	Module d'exploitation des samples tous formats en 3D	//
//////////////////////////////////////////////////////////////
*/
/* #define USE_VIRTUAL_VOICES_FOR_WAV  */
 
#include "SNDinc.h"
 
#include "sndxd.h"
#include "sndvirt.h"
 
#if defined(_DLL_COMPILATION_MODE) 
#include "snddll.h"
#else
#include "sndvect.h"
#include "sndspace.h"
#ifndef DISABLE_MPEG
#include "sndmpeg.h"
#endif /*DISABLE_MPEG*/
#ifdef USE_DBG_MODULE
#include "snddbg.h"
#endif
#endif /*_DLL_COMPILATION_MODE*/
 
#include "sndres.h"
#include "sndxdwav.h"
#ifndef DISABLE_ADPCM
#include "sndxdapm.h"
#endif /*DISABLE_ADPCM*/
#ifndef DISABLE_SNDSTRM
#include "sndstrm.h"
#endif /*DISABLE_SNDSTRM*/
 
 
/*---description des micros*/
typedef struct _micro_description *p_micro_description;
 
SNDLST2_M_DynamicUseListOf(p_micro_description);
 
typedef struct _micro_description{
	SndVector	pos;
	SndVector	vit;
	SndVector	dir_nor;
	SndVector	dir_tan;
	SndBool_field_decl(just_created);	/*TRUE entre Create et 1° affectation*/
	SndBool_field_decl(valid);
    SNDLST2_M_DynamicElementDeclaration(p_micro_description)
} micro_description;
 
typedef struct _micro_list{
    SNDLST2_M_DynamicAnchorDeclaration(p_micro_description) pList;
} micro_list;
 
static int g_iNbMicrosSxd;
static micro_list micros_sxd;
 
/*---description des samples actifs*/
typedef struct _sample_actif *p_sample_actif;
 
SNDLST2_M_DynamicUseListOf(p_sample_actif);
 
typedef struct _sample_actif{
    tduRefRes   uRes;
    long        lVoice;
    tdeTypeZip  eZip;
    SndBool     bStream;
    SNDLST2_M_DynamicElementDeclaration(p_sample_actif)
} sample_actif;
 
typedef struct _sample_list{
    SNDLST2_M_DynamicAnchorDeclaration(p_sample_actif) pList;
} sample_list;
 
static sample_list samples_sxd;
 
#ifndef DISABLE_BUFFER_CLIENT
/*----liste des buffers clients*/
typedef struct CLIENT_BUFFER_ *pCLIENT_BUFFER;
 
SNDLST2_M_DynamicUseListOf(pCLIENT_BUFFER);
 
typedef struct CLIENT_BUFFER_{
	SND_tduTypeCallback eType;
	long			lId;
	SNDLST2_M_DynamicElementDeclaration(pCLIENT_BUFFER)
} CLIENT_BUFFER;
 
typedef struct LISTE_CLIENT_BUFFER_{
	SNDLST2_M_DynamicAnchorDeclaration(pCLIENT_BUFFER) pList;
} LISTE_CLIENT_BUFFER;
#endif /* DISABLE_BUFFER_CLIENT*/
 
/*static LISTE_CLIENT_BUFFER ListBufferClient;*/
 
 
/*static tduRefRes SXD_RES_FANTOME={(unsigned long)SND_C_RES_FANTOME_PTR};*/
 
/*modules virtuels*/
#ifdef USE_VIRTUAL_VOICES_FOR_WAV
SND_tdhVirtualModule hWAVVirtModule=NULL;
#endif
#ifndef DISABLE_ADPCM
SND_tdhVirtualModule hADPCMVirtModule=NULL;
#endif
 
#ifndef DISABLE_BUFFER_CLIENT
/*pour les buffers clients stack*/
long CreateNewBufferStack(SND_tdstFormat* pformat,SND_tdstCallback* pCallback,SoundParam* par,long user_id);
SndReal GetPosBufferStack(long id_buffer);
long PushBufferStack(long id_buffer,SND_tdstStackBuffer* pStack);
void SetParamBufferStack(long id_buffer,SoundParam *par);
void DeleteBufferStack(long id_buffer);
void PauseBufferStack(long id_buffer);
void ResumeBufferStack(long id_buffer);
long GetPosBufferStackEx(long id_buffer);
#endif /* DISABLE_BUFFER_CLIENT*/
 
 
/*------------------------------------------------------------*/
/*	SND_fn_vParam3Dto2D: convertir un SoundParam en SampleParam*/
/*	Entrees:SoundParam=parametres 3D d'entree*/
/*		SampleParam=parametres 2D de sortie*/
/*	Sortie:neant*/
/*------------------------------------------------------------*/
void SND_CALL SND_fn_vParam3Dto2D(SoundParam *par3D,SampleParam *par2D)
{
	SndReal			dist,doppler;
	unsigned char	vol,pan,space;
	int				volr,voll,volb,i,j;
	SndVector		vect;
    p_micro_description   pMicro;
 
	if (par3D->iFlags & C_SOUNDPARAM_NO_POSITION)
	{/*pas de poditionnement 3D -> extra params*/
		if (par3D->iFlags & C_SOUNDPARAM_COEF_VOL)
			par2D->ucVol=par3D->ucVol;
		else
			par2D->ucVol=C_SOUNDVOL_MAXI;
 
		par2D->Freq=par3D->Freq;
		par2D->ucPan=par3D->ucPan;
		par2D->ucSpace=par3D->ucSpace;
	}
	else
	if (g_iNbMicrosSxd)
	{/*au moins 1 micro*/
		vol=0;pan=C_SOUNDPAN_MEDIAN;space=C_SOUNDSPACE_FRONT;
        volr=0;voll=0;volb=0;doppler=C_SNDREAL_1;
 
		SNDLST2_M_DynamicForEachElementOf(&micros_sxd.pList,pMicro,i)
        {/*for each active micro*/
			if (!pMicro->just_created)
			{
				for (j=0;j<par3D->iNbLinks;j++)
				{
					if (par3D->astMicro[j].lId==(long)pMicro) break;
				}
				if (j<par3D->iNbLinks)
				{
					if (par3D->astMicro[j].bLinked)
					{
						vect.x=par3D->Pos.x-pMicro->pos.x;
						vect.y=par3D->Pos.y-pMicro->pos.y;
						vect.z=par3D->Pos.z-pMicro->pos.z;
						
						dist=SND_fn_rPseudoNormeVectorSnd(&vect);
						if (par3D->iFlags & C_SOUNDPARAM_ROLLOFF)
							vol=SND_fn_ucDistanceToVolumeEx(dist,&(SND_M_GetExtraParamFromSoundParam(par3D))->stRollOff);
						else
							vol=SND_fn_ucDistanceToVolume(dist);
						pan=SND_fn_ucPositionToPan(&(par3D->Pos),&(pMicro->pos),&(pMicro->dir_nor),&(pMicro->dir_tan));
						space=SND_fn_ucPositionToDolby(&(par3D->Pos),&(pMicro->pos),&(pMicro->dir_nor));
						doppler=SND_fn_rDopplerPitch(&(par3D->Pos),&(par3D->Vit),&(pMicro->pos),&(pMicro->vit));
						
						volr+=M_VolFront(M_VolLeft(vol,pan),space);
						voll+=M_VolFront(M_VolRight(vol,pan),space);
						volb+=M_VolBack(vol,space);
					}
				}
			}
		}
 
		if (i==1)
		{
			par2D->ucVol=vol;
			par2D->ucPan=pan;
			par2D->ucSpace=space;
			par2D->Freq=doppler;
		}
		else
		{
			voll=voll/i;volr=volr/i;volb=volb/i;
			par2D->ucVol=M_GetVol(volr,voll,volb);
			par2D->ucPan=M_GetPan(volr,voll,volb);
			par2D->ucSpace=M_GetSpace(volr,voll,volb);
 
			par2D->Freq=C_SNDREAL_1;/*pas de doppler*/
		}
 
/*        if (par3D->iFlags & C_SOUNDPARAM_COEF_FREQ)*/
            par2D->Freq=SND_fn_rMulRealRealSnd(par2D->Freq,par3D->Freq);
 
        if (par3D->iFlags & C_SOUNDPARAM_COEF_VOL)
            par2D->ucVol=(unsigned char)(((long)par2D->ucVol*par3D->ucVol)>>7);
	}
	else
	{/* pas de micro*/
		memcpy(par2D,&C_SAMPLEPARAM_NEUTRE,sizeof(*par2D));
		par2D->Freq=par3D->Freq;
	}
	par2D->ucReverb=par3D->ucReverb;
}
 
/*---------------------------------------------------------------*/
/*	SND_fn_rGetNormeSxd:retourne une norme sur l'objet (distance au(x) micro(s)*/
/*	Entrees: position de l'objet concerne*/
/*	Sortie:	normeconcernant l'objet; sera utilise pour classer les objets dans l'ordre des distances croissantes*/
SndReal SND_CALL SND_fn_rGetNormeSxd(SoundParam* par3D)
{
	SndReal				dist;
	unsigned char		vol;
	int					i,j;
	SndVector			vect;
    p_micro_description pMicro;
	unsigned char		ret_vol=0;
 
	if (g_iNbMicrosSxd)
	{/*au moins 1 micro*/
		SNDLST2_M_DynamicForEachElementOf(&micros_sxd.pList,pMicro,i)
        {/*for each active micro*/
			vol=0;
 
			if (!pMicro->just_created)
			{
				for (j=0;j<par3D->iNbLinks;j++)
				{
					if (par3D->astMicro[j].lId==(long)pMicro) break;
				}
				if (j<par3D->iNbLinks)
				{
					if (par3D->astMicro[j].bLinked)
					{
						vect.x=par3D->Pos.x-pMicro->pos.x;
						vect.y=par3D->Pos.y-pMicro->pos.y;
						vect.z=par3D->Pos.z-pMicro->pos.z;
						
						dist=SND_fn_rPseudoNormeVectorSnd(&vect);
						if (par3D->iFlags & C_SOUNDPARAM_ROLLOFF)
							vol=SND_fn_ucDistanceToVolumeEx(dist,&(SND_M_GetExtraParamFromSoundParam(par3D))->stRollOff);
						else
							vol=SND_fn_ucDistanceToVolume(dist);
					}
				}
			}
 
			ret_vol=max(ret_vol,vol);
		}
	}
 
	return M_IntToRealSnd(ret_vol);
}
 
 
sample_actif *new_sample_sxd(long voice,tdeTypeZip zip,SndBool stream,tduRefRes res)
{
    p_sample_actif sample;
    int i;
 
    SNDLST2_M_DynamicForEachElementOf(&samples_sxd.pList,sample,i)
    {
        if ((sample->lVoice==voice)
			&& (sample->eZip==zip) 
			&& ((sample->bStream==stream) || (sample->eZip!=SAMPLE_PCM)))
        {//the same PlayXXX function returned twice the same value -> reuse the same Sxd Voice
            sample->uRes=res;
            return sample;
        }
    }
 
    sample=SND_fn_pvMallocSndEx(E_ucSndBlockMain,sizeof(sample_actif));
    SNDLST2_M_DynamicInitElement(sample);
    SNDLST2_M_DynamicAddTail(&samples_sxd.pList,sample);
    sample->uRes=res;
    sample->lVoice=voice;
    sample->eZip=zip;
    sample->bStream=stream;
 
    return sample;
}
 
void del_sample_actif(p_sample_actif sample)
{
    SNDLST2_M_DynamicIsolate(sample);
    SND_fn_vFreeSndEx(E_ucSndBlockMain,sample);
}
 
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*		Definitions des fonctions publiques*/
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
#ifndef DISABLE_MULTIWAVFORMAT
/*----------------------------------------------*/
/*	PlaySxd: jouer un son*/
/*	Entrees:res=designation de la ressource*/
/*		par=parametres 3D*/
/*		prio=niveau de priorite*/
/*		fct=fonction de callback*/
/*-----------------------------------------------*/
long SND_CALL SND_fn_lPlaySxd(tduRefRes res,SoundParam *par,long prio,SND_td_pfn_vSoundCallback fn_callback,long par_callback)
{
#ifndef DISABLE_MPEG
	SampleParam	    par2D;
#endif
    long            ret;
    sample_actif    *sample;
 
    switch (res.pstPtr->uRes.stSample.eZip)
    {
    case SAMPLE_PCM:
#ifndef DISABLE_SNDSTRM
        if (res.pstPtr->uRes.stSample.bStream)
            ret=SND_fn_lPlaySxdStream(res,par,prio,fn_callback,par_callback);
        else
#endif /*DISABLE_SNDSTRM*/
#ifndef USE_VIRTUAL_VOICES_FOR_WAV
            ret=SND_fn_lPlaySxdWave(res,par,prio,fn_callback,par_callback);
#else
            ret=SND_fn_lPlaySxdVirtual(hWAVVirtModule,res,par,prio,fn_callback,par_callback);
#endif /*USE_VIRTUAL_VOICES_FOR_WAV*/
        break;
#ifndef DISABLE_MPEG
    case SAMPLE_MPEG:
	    SND_fn_vParam3Dto2D(par,&par2D);
        ret=SND_fn_lPlayMPEG(res,&par2D,prio,fn_callback,par_callback);
        break;
#endif /*DISABLE_MPEG*/
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
        ret=SND_fn_lPlaySxdVirtual(hADPCMVirtModule,res,par,prio,fn_callback,par_callback);
		/*ret=SND_fn_lPlaySxdADPCM(res,par,prio,fn_callback,par_callback);*/
		break;
#endif /*DISABLE_ADPCM*/
    default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
        ret=C_PLAY_FAILED;
        break;
    }
 
    if (ret!=C_PLAY_FAILED)
    {
        sample=new_sample_sxd(ret,res.pstPtr->uRes.stSample.eZip,res.pstPtr->uRes.stSample.bStream,res);
 
        return (long)sample;
    }
    else
        return C_PLAY_FAILED;
}
 
void SND_CALL SND_fn_vRemoveCallbackSxd(long voice)
{
    switch (((sample_actif*)voice)->eZip)
    {
    case SAMPLE_PCM:
#ifndef DISABLE_SNDSTRM
        if (((sample_actif*)voice)->bStream)
            SND_fn_vRemoveCallbackSxdStream(((sample_actif*)voice)->lVoice);
        else
#endif /*DISABLE_SNDSTRM*/
#ifndef USE_VIRTUAL_VOICES_FOR_WAV
            SND_fn_vRemoveCallbackSxdWave(((sample_actif*)voice)->lVoice);
#else
		SND_fn_vRemoveCallbackSxdVirtual(hWAVVirtModule,((sample_actif*)voice)->lVoice);
#endif
        break;
#ifndef DISABLE_MPEG
    case SAMPLE_MPEG:
        SND_fn_vRemoveCallbackMPEG(((sample_actif*)voice)->lVoice);
        break;
#endif
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
		SND_fn_vRemoveCallbackSxdVirtual(hADPCMVirtModule,((sample_actif*)voice)->lVoice);
        /*SND_fn_vRemoveCallbackSxdADPCM(((sample_actif*)voice)->lVoice);*/
		break;
#endif
    default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
        break;
    }
}
 
SndBool SND_CALL SND_fn_bSetParamSxd(long voice,SoundParam *par)
{
    SndBool ret;
#ifndef DISABLE_MPEG
	SampleParam par2D;
#endif
 
    switch (((sample_actif*)voice)->eZip)
    {
    case SAMPLE_PCM:
#ifndef DISABLE_SNDSTRM
        if (((sample_actif*)voice)->bStream)
            ret=SND_fn_bSetParamSxdStream(((sample_actif*)voice)->lVoice,par);
        else
#endif /*DISABLE_SNDSTRM*/
#ifndef USE_VIRTUAL_VOICES_FOR_WAV
            ret=SND_fn_bSetParamSxdWave(((sample_actif*)voice)->lVoice,par);
#else
			ret=SND_fn_bSetParamSxdVirtual(hWAVVirtModule,((sample_actif*)voice)->lVoice,par);
#endif
        break;
#ifndef DISABLE_MPEG
    case SAMPLE_MPEG:
    	SND_fn_vParam3Dto2D(par,&par2D);
        ret=SND_fn_bSetParamMPEG(((sample_actif*)voice)->lVoice,&par2D);
        break;
#endif
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
		ret=SND_fn_bSetParamSxdVirtual(hADPCMVirtModule,((sample_actif*)voice)->lVoice,par);
/*        ret=SND_fn_bSetParamSxdADPCM(((sample_actif*)voice)->lVoice,par);*/
		break;
#endif
    default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
        ret=FALSE;
        break;
    }
 
    if (!ret)
        del_sample_actif((p_sample_actif)voice);
 
    return ret;
}
 
SndBool SND_CALL SND_fn_bTestIsPlayingSxd(long voice)
{
    SndBool ret;
 
    switch (((sample_actif*)voice)->eZip)
    {
    case SAMPLE_PCM:
#ifndef DISABLE_SNDSTRM
        if (((sample_actif*)voice)->bStream)
            ret=SND_fn_bTestIsPlayingSxdStream(((sample_actif*)voice)->lVoice);
        else
#endif /*DISABLE_SNDSTRM*/
#ifndef USE_VIRTUAL_VOICES_FOR_WAV
            ret=SND_fn_bTestIsPlayingSxdWave(((sample_actif*)voice)->lVoice);
#else
			ret=SND_fn_bTestIsPlayingSxdVirtual(hWAVVirtModule,((sample_actif*)voice)->lVoice);
#endif
        break;
#ifndef DISABLE_MPEG
    case SAMPLE_MPEG:
        ret=SND_fn_bTestIsPlayingMPEG(((sample_actif*)voice)->lVoice);
        break;
#endif
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
		ret=SND_fn_bTestIsPlayingSxdVirtual(hADPCMVirtModule,((sample_actif*)voice)->lVoice);
/*        ret=SND_fn_bTestIsPlayingSxdADPCM(((sample_actif*)voice)->lVoice);*/
		break;
#endif
    default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
        ret=FALSE;
        break;
    }
 
    if (!ret)
        del_sample_actif((p_sample_actif)voice);
 
    return ret;
}
 
void SND_CALL SND_fn_vStopSxd(long voice)
{
    switch (((sample_actif*)voice)->eZip)
    {
    case SAMPLE_PCM:
#ifndef DISABLE_SNDSTRM
        if (((sample_actif*)voice)->bStream)
            SND_fn_vStopSxdStream(((sample_actif*)voice)->lVoice);
        else
#endif /*DISABLE_SNDSTRM*/
#ifndef USE_VIRTUAL_VOICES_FOR_WAV
            SND_fn_vStopSxdWave(((sample_actif*)voice)->lVoice);
#else
			SND_fn_vStopSxdVirtual(hWAVVirtModule,((sample_actif*)voice)->lVoice);
#endif
        break;
#ifndef DISABLE_MPEG
    case SAMPLE_MPEG:
        SND_fn_vStopMPEG(((sample_actif*)voice)->lVoice);
        break;
#endif
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
/*        SND_fn_vStopSxdADPCM(((sample_actif*)voice)->lVoice);*/
		SND_fn_vStopSxdVirtual(hADPCMVirtModule,((sample_actif*)voice)->lVoice);
		break;
#endif
    default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
        break;
    }
 
    del_sample_actif((p_sample_actif)voice);
}
 
void SND_CALL SND_fn_vPauseSxd(long voice)
{
    switch (((sample_actif*)voice)->eZip)
    {
    case SAMPLE_PCM:
#ifndef DISABLE_SNDSTRM
        if (((sample_actif*)voice)->bStream)
            SND_fn_vPauseSxdStream(((sample_actif*)voice)->lVoice);
        else
#endif /*DISABLE_SNDSTRM*/
#ifndef USE_VIRTUAL_VOICES_FOR_WAV
            SND_fn_vPauseSxdWave(((sample_actif*)voice)->lVoice);
#else
			SND_fn_vPauseSxdVirtual(hWAVVirtModule,((sample_actif*)voice)->lVoice);
#endif
        break;
#ifndef DISABLE_MPEG
    case SAMPLE_MPEG:
        SND_fn_vPauseMPEG(((sample_actif*)voice)->lVoice);
        break;
#endif
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
/*		SND_fn_vPauseSxdADPCM(((sample_actif*)voice)->lVoice);*/
		SND_fn_vPauseSxdVirtual(hADPCMVirtModule,((sample_actif*)voice)->lVoice);
		break;
#endif
    default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
        break;
    }
}
 
void SND_CALL SND_fn_vResumeSxd(long voice)
{
    switch (((sample_actif*)voice)->eZip)
    {
    case SAMPLE_PCM:
#ifndef DISABLE_SNDSTRM
        if (((sample_actif*)voice)->bStream)
            SND_fn_vResumeSxdStream(((sample_actif*)voice)->lVoice);
        else
#endif /*DISABLE_SNDSTRM*/
#ifndef USE_VIRTUAL_VOICES_FOR_WAV
            SND_fn_vResumeSxdWave(((sample_actif*)voice)->lVoice);
#else
			SND_fn_vResumeSxdVirtual(hWAVVirtModule,((sample_actif*)voice)->lVoice);
#endif
		break;
#ifndef DISABLE_MPEG
    case SAMPLE_MPEG:
        SND_fn_vResumeMPEG(((sample_actif*)voice)->lVoice);
        break;
#endif
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
/*        SND_fn_vResumeSxdADPCM(((sample_actif*)voice)->lVoice);*/
		SND_fn_vResumeSxdVirtual(hADPCMVirtModule,((sample_actif*)voice)->lVoice);
		break;
#endif
    default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
        break;
    }
}
 
/*--------------------------------------------------*/
/*	SND_fnvConvertRsvDiskToMemSxd*/
/*	Entree:disk=bloxkResDisk à convertir*/
/*		mem=blockMemDisk à generer*/
/*		ptrBegin=adresse de stockage des donnees*/
/*	Retour:neant*/
/*------------------------------------------------*/
void SND_CALL SND_fn_vConvertResDiskToMemSxd(tdstBlockResourceDisk *disk
						 ,tdstBlockResourceMem *mem
						 ,void* ptrBegin)
{
    switch (disk->uRes.stSample.eZip)
    {
    case SAMPLE_PCM:/*only oen type is availbale for this function*/
	    SND_fn_vConvertResDiskToMemSxdWave(disk,mem,ptrBegin);
        break;
    default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
        break;
    }
}
 
 
#if !defined(NO_ACP_SCRIPT) || defined(_DLL_COMPILATION_MODE)
/*this function must be defined in Script/Hybrid or DLL mode*/
SndBool SND_CALL SND_fn_bLoadResScriptSxd(tdstBlockResourceDisk* disk,tdstBlockResourceMem* mem)
{
	/*init indispensables*/
	mem->uRes.stSample.eZip=disk->uRes.stSample.eZip;
 
    switch (disk->uRes.stSample.eZip)
    {
    case SAMPLE_PCM:
	case SAMPLE_AIFF:
#ifndef DISABLE_SNDSTRM
        if (disk->uRes.stSample.bStream)
			return(SND_fn_bLoadResScriptSxdStream(disk,mem));
		else
#endif /*DISABLE_SNDSTRM*/
			return(SND_fn_bLoadResScriptSxdWave(disk,mem));
#ifndef DISABLE_MPEG
    case SAMPLE_MPEG:
	    return(SND_fn_bLoadResScriptMPEG(disk,mem));
#endif
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
	case SAMPLE_ADPCM_TO_CONVERT:
		#ifdef SPEEDBUSTER
		if (_strcmpi(disk->uRes.stSample.czFileName,"silence.apm")==0)
			return FALSE;
		#endif
		if (SND_fn_b3DOneShootShouldBeConvertedSxdWave() && (disk->uRes.stSample.uwNbChannels==1))
			/*when hardware3D enabled, convert mono-sounds from ADPCM to PCM */
			return(SND_fn_bLoadResScriptAndConvertToWAVSxdADPCM(disk,mem));
		else
			return(SND_fn_bLoadResScriptSxdADPCM(disk,mem));
#endif
    default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
        return FALSE;
    }
}
#endif
 
SndBool SND_CALL SND_fn_bLoadResBinarySxd(tdstBlockResourceDisk* disk,tdstBlockResourceMem* mem,char* data)
{
	/*init indispensables*/
	mem->uRes.stSample.eZip=disk->uRes.stSample.eZip;
 
    switch (disk->uRes.stSample.eZip)
    {
    case SAMPLE_PCM:
#ifndef DISABLE_SNDSTRM
        if (disk->uRes.stSample.bStream)
			return(SND_fn_bLoadResBinarySxdStream(disk,mem,data));
		else
#endif /*DISABLE_SNDSTRM*/
			return(SND_fn_bLoadResBinarySxdWave(disk,mem,data));
#ifndef DISABLE_MPEG
    case SAMPLE_MPEG:
	    return(SND_fn_bLoadResBinaryMPEG(disk,mem,data));
#endif
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
	case SAMPLE_ADPCM_TO_CONVERT:
		#ifdef SPEEDBUSTER
		if (_strcmpi(disk->uRes.stSample.czFileName,"silence.apm")==0)
			return FALSE;
		#endif
		if (SND_fn_b3DOneShootShouldBeConvertedSxdWave() && (disk->uRes.stSample.uwNbChannels==1))
			/*when hardware3D enabled, convert mono-sounds from ADPCM to PCM */
		    return(SND_fn_bLoadResBinaryAndConvertToWAVSxdADPCM(disk,mem,data));
		else
			return(SND_fn_bLoadResBinarySxdADPCM(disk,mem,data));
#endif
	case SAMPLE_AIFF:
		/*sample AIFF non tolere en binaire*/
    default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
        return FALSE;
    }
}
 
 
 
/*--------------------------------------------------*/
/*	SND_fnvUnLoadRsvDisk*/
/*	Entree:mem=blockMemDisk à liberer*/
/*	Retour:neant*/
/*------------------------------------------------*/
void SND_CALL SND_fn_vUnLoadResSxd(tdstBlockResourceMem* mem)
{
    switch (mem->uRes.stSample.eZip)
    {
    case SAMPLE_PCM:
#ifndef DISABLE_SNDSTRM
		if (mem->uRes.stSample.bStream)
			SND_fn_vUnLoadResSxdStream(mem);
		else
#endif /*DISABLE_SNDSTRM*/
			SND_fn_vUnLoadResSxdWave(mem);
        break;
#ifndef DISABLE_MPEG
    case SAMPLE_MPEG:
	    SND_fn_vUnLoadResMPEG(mem);
        break;
#endif
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
	    SND_fn_vUnLoadResSxdADPCM(mem);
		break;
#endif
    default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
        break;
    }
}
 
/*---------------------------------------------------------*/
/*      IsResLoadedSample: teste si une ressource est operationnelle*/
/*      Entree:blockmem valide*/
/*      Sortie:TRUE si SndPlay acceptable*/
/*---------------------------------------------------------*/
SndBool SND_CALL SND_fn_bIsResLoadedSxd(tdstBlockResourceMem *mem)
{
    switch (mem->uRes.stSample.eZip)
    {
    case SAMPLE_PCM:
    	return SND_fn_bIsResLoadedSxdWave(mem);
#ifndef DISABLE_MPEG
    case SAMPLE_MPEG:
	    return SND_fn_bIsResLoadedMPEG(mem);
#endif
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
    	return SND_fn_bIsResLoadedSxdADPCM(mem);
#endif
    default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
        return FALSE;
    }
}
 
/*----------------------------------------------------------------*/
/*	IsResourceLooping: indique si la ressource est bouclante*/
/*	Entree: ressource concernee*/
/*	Sortie: TRUE si la ressource est bouclante, FALSE si elle est one-shoot*/
/*-----------------------------------------------------------------*/
SndBool   SND_CALL SND_fn_bIsResourceLoopingSxd(tduRefRes res)
{
    switch (res.pstPtr->uRes.stSample.eZip)
    {
    case SAMPLE_PCM:
		return SND_fn_bIsResourceLoopingSxdWave(res);
        break;
#ifndef DISABLE_MPEG
    case SAMPLE_MPEG:/*unknown for MPEG*/
		return FALSE;
        break;
#endif
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
		return SND_fn_bIsResourceLoopingSxdADPCM(res);
		break;
#endif
	default:
		return FALSE;
		break;
	}
}
 
/*---------------------------------------------------------*/
/*	GetPos: retourne la position "theorique" de la ressource*/
/*			exprime en seconde depuis le debut*/
/*			different du temps absolu (car pitch, derive..)*/
/*	Entree: voie concernee*/
/*	Sortie: temps en S (SndReal)*/
/*----------------------------------------------------------*/
SndReal SND_CALL SND_fn_rGetPosSxd(long voie)
{
    switch (((sample_actif*)voie)->eZip)
    {
    case SAMPLE_PCM:
#ifndef DISABLE_SNDSTRM
        if (((sample_actif*)voie)->bStream)
            return SND_fn_rGetPosSxdStream(((sample_actif*)voie)->lVoice);
        else
#endif /*DISABLE_SNDSTRM*/
#ifndef USE_VIRTUAL_VOICES_FOR_WAV
            return SND_fn_rGetPosSxdWave(((sample_actif*)voie)->lVoice);
#else
			return SND_fn_rGetPosSxdVirtual(hWAVVirtModule,((sample_actif*)voie)->lVoice);
#endif
			break;
#ifndef DISABLE_MPEG
    case SAMPLE_MPEG:
        return SND_fn_rGetPosMPEG(((sample_actif*)voie)->lVoice);
        break;
#endif
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
		return SND_fn_rGetPosSxdVirtual(hADPCMVirtModule,((sample_actif*)voie)->lVoice);
/*        return SND_fn_rGetPosSxdADPCM(((sample_actif*)voie)->lVoice);*/
		break;
#endif
    default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
		return SND_C_POS_UNKNOWN;
        break;
    }
}
 
/*---------------------------------------------------------*/
/*	GetLength: retourne la duree "theorique" de la ressource*/
/*			exprime en seconde (constant pour une ressource donnee)*/
/*	Entree: voie concernee*/
/*	Sortie: duree en S (SndReal)*/
/*----------------------------------------------------------*/
SndReal SND_CALL SND_fn_rGetLengthSxd(long voie)
{
    switch (((sample_actif*)voie)->eZip)
    {
    case SAMPLE_PCM:
#ifndef DISABLE_SNDSTRM
        if (((sample_actif*)voie)->bStream)
            return SND_fn_rGetLengthSxdStream(((sample_actif*)voie)->lVoice);
        else
#endif /*DISABLE_SNDSTRM*/
#ifndef USE_VIRTUAL_VOICES_FOR_WAV
            return SND_fn_rGetLengthSxdWave(((sample_actif*)voie)->lVoice);
#else
			return SND_fn_rGetLengthSxdVirtual(hWAVVirtModule,((sample_actif*)voie)->lVoice);
#endif
        break;
#ifndef DISABLE_MPEG
    case SAMPLE_MPEG:
        return SND_fn_rGetLengthMPEG(((sample_actif*)voie)->lVoice);
        break;
#endif
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
		return SND_fn_rGetLengthSxdVirtual(hADPCMVirtModule,((sample_actif*)voie)->lVoice);
/*		return SND_fn_rGetLengthSxdADPCM(((sample_actif*)voie)->lVoice);*/
		break;
#endif
    default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
		return SND_C_LENGTH_UNKNOWN;
        break;
    }
}
 
SndBool SND_CALL SND_fn_bCheckVersionResourceSxd(tdstBlockResourceDisk* disk)
{
    switch (disk->uRes.stSample.eZip)
    {
    case SAMPLE_PCM:
		return SND_fn_bCheckVersionResourceSxdWave(disk);
        break;
#ifndef DISABLE_MPEG
    case SAMPLE_MPEG:
		return SND_fn_bCheckVersionResourceMPEG(disk);
        break;
#endif
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
		return SND_fn_bCheckVersionResourceSxdADPCM(disk);
		break;
#endif
    default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
		return FALSE;
        break;
    }
 
}
 
 
 
#else /*DISABLE_MULTIWAVFORMAT*/
 
 
 
/*----------------------------------------------*/
/*	PlaySxd: jouer un son*/
/*	Entrees:res=designation de la ressource*/
/*		par=parametres 3D*/
/*		prio=niveau de priorite*/
/*		fct=fonction de callback*/
/*-----------------------------------------------*/
long SND_CALL SND_fn_lPlaySxd(tduRefRes res,SoundParam *par,long prio,SND_td_pfn_vSoundCallback fn_callback,long par_callback)
{
    long            ret;
    sample_actif    *sample;
 
#ifndef DISABLE_SNDSTRM
    if (res.pstPtr->uRes.stSample.bStream)
        ret=SND_fn_lPlaySxdStream(res,par,prio,fn_callback,par_callback);
    else
#endif /*DISABLE_SNDSTRM*/
#ifndef USE_VIRTUAL_VOICES_FOR_WAV
        ret=SND_fn_lPlaySxdWave(res,par,prio,fn_callback,par_callback);
#else
        ret=SND_fn_lPlaySxdVirtual(hWAVVirtModule,res,par,prio,fn_callback,par_callback);
#endif
 
    if (ret!=C_PLAY_FAILED)
    {
        sample=new_sample_sxd(ret,SAMPLE_PCM,res.pstPtr->uRes.stSample.bStream,res);
 
        return (long)sample;
    }
    else
        return C_PLAY_FAILED;
}
 
void SND_CALL SND_fn_vRemoveCallbackSxd(long voice)
{
#ifndef DISABLE_SNDSTRM
    if (((sample_actif*)voice)->bStream)
        SND_fn_vRemoveCallbackSxdStream(((sample_actif*)voice)->lVoice);
    else
#endif /*DISABLE_SNDSTRM*/
#ifndef USE_VIRTUAL_VOICES_FOR_WAV
        SND_fn_vRemoveCallbackSxdWave(((sample_actif*)voice)->lVoice);
#else
	SND_fn_vRemoveCallbackSxdVirtual(hWAVVirtModule,((sample_actif*)voice)->lVoice);
#endif
}
 
SndBool SND_CALL SND_fn_bSetParamSxd(long voice,SoundParam *par)
{
    SndBool ret;
 
#ifndef DISABLE_SNDSTRM
    if (((sample_actif*)voice)->bStream)
        ret=SND_fn_bSetParamSxdStream(((sample_actif*)voice)->lVoice,par);
    else
#endif /*DISABLE_SNDSTRM*/
#ifndef USE_VIRTUAL_VOICES_FOR_WAV
        ret=SND_fn_bSetParamSxdWave(((sample_actif*)voice)->lVoice,par);
#else
		ret=SND_fn_bSetParamSxdVirtual(hWAVVirtModule,((sample_actif*)voice)->lVoice,par);
#endif
 
    if (!ret)
        del_sample_actif((p_sample_actif)voice);
 
    return ret;
}
 
SndBool SND_CALL SND_fn_bTestIsPlayingSxd(long voice)
{
    SndBool ret;
 
#ifndef DISABLE_SNDSTRM
    if (((sample_actif*)voice)->bStream)
        ret=SND_fn_bTestIsPlayingSxdStream(((sample_actif*)voice)->lVoice);
    else
#endif /*DISABLE_SNDSTRM*/
#ifndef USE_VIRTUAL_VOICES_FOR_WAV
        ret=SND_fn_bTestIsPlayingSxdWave(((sample_actif*)voice)->lVoice);
#else
		ret=SND_fn_bTestIsPlayingSxdVirtual(hWAVVirtModule,((sample_actif*)voice)->lVoice);
#endif
 
    if (!ret)
        del_sample_actif((p_sample_actif)voice);
 
    return ret;
}
 
void SND_CALL SND_fn_vStopSxd(long voice)
{
#ifndef DISABLE_SNDSTRM
    if (((sample_actif*)voice)->bStream)
        SND_fn_vStopSxdStream(((sample_actif*)voice)->lVoice);
    else
#endif /*DISABLE_SNDSTRM*/
#ifndef USE_VIRTUAL_VOICES_FOR_WAV
        SND_fn_vStopSxdWave(((sample_actif*)voice)->lVoice);
#else
		SND_fn_vStopSxdVirtual(hWAVVirtModule,((sample_actif*)voice)->lVoice);
#endif
 
    del_sample_actif((p_sample_actif)voice);
}
 
void SND_CALL SND_fn_vPauseSxd(long voice)
{
#ifndef DISABLE_SNDSTRM
    if (((sample_actif*)voice)->bStream)
        SND_fn_vPauseSxdStream(((sample_actif*)voice)->lVoice);
    else
#endif /*DISABLE_SNDSTRM*/
#ifndef USE_VIRTUAL_VOICES_FOR_WAV
        SND_fn_vPauseSxdWave(((sample_actif*)voice)->lVoice);
#else
		SND_fn_vPauseSxdVirtual(hWAVVirtModule,((sample_actif*)voice)->lVoice);
#endif
}
 
void SND_CALL SND_fn_vResumeSxd(long voice)
{
#ifndef DISABLE_SNDSTRM
    if (((sample_actif*)voice)->bStream)
        SND_fn_vResumeSxdStream(((sample_actif*)voice)->lVoice);
    else
#endif /*DISABLE_SNDSTRM*/
#ifndef USE_VIRTUAL_VOICES_FOR_WAV
        SND_fn_vResumeSxdWave(((sample_actif*)voice)->lVoice);
#else
		SND_fn_vResumeSxdVirtual(hWAVVirtModule,((sample_actif*)voice)->lVoice);
#endif
}
 
/*--------------------------------------------------*/
/*	SND_fnvConvertRsvDiskToMemSxd*/
/*	Entree:disk=bloxkResDisk à convertir*/
/*		mem=blockMemDisk à generer*/
/*		ptrBegin=adresse de stockage des donnees*/
/*	Retour:neant*/
/*------------------------------------------------*/
void SND_CALL SND_fn_vConvertResDiskToMemSxd(tdstBlockResourceDisk *disk
						 ,tdstBlockResourceMem *mem
						 ,void* ptrBegin)
{
    SND_fn_vConvertResDiskToMemSxdWave(disk,mem,ptrBegin);
}
 
 
#if !defined(NO_ACP_SCRIPT) || defined(_DLL_COMPILATION_MODE)
/*this function must be defined in Script/Hybrid or DLL mode*/
SndBool SND_CALL SND_fn_bLoadResScriptSxd(tdstBlockResourceDisk* disk,tdstBlockResourceMem* mem)
{
#ifndef DISABLE_SNDSTRM
    if (disk->uRes.stSample.bStream)
		return(SND_fn_bLoadResScriptSxdStream(disk,mem));
	else
#endif /*DISABLE_SNDSTRM*/
		return(SND_fn_bLoadResScriptSxdWave(disk,mem));
}
#endif
 
SndBool SND_CALL SND_fn_bLoadResBinarySxd(tdstBlockResourceDisk* disk,tdstBlockResourceMem* mem,char* data)
{
#ifndef DISABLE_SNDSTRM
    if (disk->uRes.stSample.bStream)
		return(SND_fn_bLoadResBinarySxdStream(disk,mem,data));
	else
#endif /*DISABLE_SNDSTRM*/
		return(SND_fn_bLoadResBinarySxdWave(disk,mem,data));
}
 
 
 
/*--------------------------------------------------*/
/*	SND_fnvUnLoadRsvDisk*/
/*	Entree:mem=blockMemDisk à liberer*/
/*	Retour:neant*/
/*------------------------------------------------*/
void SND_CALL SND_fn_vUnLoadResSxd(tdstBlockResourceMem* mem)
{
#ifndef DISABLE_SNDSTRM
	if (mem->uRes.stSample.bStream)
		SND_fn_vUnLoadResSxdStream(mem);
	else
#endif /*DISABLE_SNDSTRM*/
		SND_fn_vUnLoadResSxdWave(mem);
}
 
/*---------------------------------------------------------*/
/*      IsResLoadedSample: teste si une ressource est operationnelle*/
/*      Entree:blockmem valide*/
/*      Sortie:TRUE si SndPlay acceptable*/
/*---------------------------------------------------------*/
SndBool SND_CALL SND_fn_bIsResLoadedSxd(tdstBlockResourceMem *mem)
{
   	return SND_fn_bIsResLoadedSxdWave(mem);
}
 
/*----------------------------------------------------------------*/
/*	IsResourceLooping: indique si la ressource est bouclante*/
/*	Entree: ressource concernee*/
/*	Sortie: TRUE si la ressource est bouclante, FALSE si elle est one-shoot*/
/*-----------------------------------------------------------------*/
SndBool   SND_CALL SND_fn_bIsResourceLoopingSxd(tduRefRes res)
{
	return SND_fn_bIsResourceLoopingSxdWave(res);
}
 
/*---------------------------------------------------------*/
/*	GetPos: retourne la position "theorique" de la ressource*/
/*			exprime en seconde depuis le debut*/
/*			different du temps absolu (car pitch, derive..)*/
/*	Entree: voie concernee*/
/*	Sortie: temps en S (SndReal)*/
/*----------------------------------------------------------*/
SndReal SND_CALL SND_fn_rGetPosSxd(long voie)
{
#ifndef DISABLE_SNDSTRM
    if (((sample_actif*)voie)->bStream)
        return SND_fn_rGetPosSxdStream(((sample_actif*)voie)->lVoice);
    else
#endif /*DISABLE_SNDSTRM*/
#ifndef USE_VIRTUAL_VOICES_FOR_WAV
        return SND_fn_rGetPosSxdWave(((sample_actif*)voie)->lVoice);
#else
		return SND_fn_rGetPosSxdVirtual(hWAVVirtModule,((sample_actif*)voie)->lVoice);
#endif
}
 
/*---------------------------------------------------------*/
/*	GetLength: retourne la duree "theorique" de la ressource*/
/*			exprime en seconde (constant pour une ressource donnee)*/
/*	Entree: voie concernee*/
/*	Sortie: duree en S (SndReal)*/
/*----------------------------------------------------------*/
SndReal SND_CALL SND_fn_rGetLengthSxd(long voie)
{
#ifndef DISABLE_SNDSTRM
    if (((sample_actif*)voie)->bStream)
        return SND_fn_rGetLengthSxdStream(((sample_actif*)voie)->lVoice);
    else
#endif /*DISABLE_SNDSTRM*/
#ifndef USE_VIRTUAL_VOICES_FOR_WAV
        return SND_fn_rGetLengthSxdWave(((sample_actif*)voie)->lVoice);
#else
		return SND_fn_rGetLengthSxdVirtual(hWAVVirtModule,((sample_actif*)voie)->lVoice);
#endif
}
 
SndBool SND_CALL SND_fn_bCheckVersionResourceSxd(tdstBlockResourceDisk* disk)
{
	return SND_fn_bCheckVersionResourceSxdWave(disk);
}
 
 
#endif /*DISABLE_MULTIWAVFORMAT*/
 
 
 
 
void SND_CALL SND_fn_vSetSoundVolumeSxd(unsigned char vol)
{
	SND_fn_vSetSoundVolumeSxdWave(vol);
}
 
unsigned char SND_CALL SND_fn_ucGetSoundVolumeSxd(void)
{
	return SND_fn_ucGetSoundVolumeSxdWave();
}
 
 
void SND_CALL SND_fn_vSetStereoSxd(SndBool active)
{
}
 
SndBool SND_CALL SND_fn_bGetStereoSxd(void)
{
	return FALSE;
}
 
void SND_CALL SND_fn_vSetReverseStereoSxd(SndBool active)
{
#ifndef DISABLE_WAVE
	SND_fn_vSetReverseStereoSxdWave(active);
#endif
#ifndef DISABLE_ADPCM
	SND_fn_vSetReverseStereoSxdADPCM(active);
#endif 

}
 
SndBool	SND_CALL SND_fn_bGetReverseStereoSxd(void)
{
	return SND_fn_bGetReverseStereoSxdWave();
}
 
 
/*---------------------------------------*/
/*	Initsxd:initialisation du module*/
/*	Entree:neant*/
/*	Sortie:code de retour (C_INIT_FAILED,C_INIT_RUNNIG ou C_INIT_OF)*/
/*---------------------------------------*/
int SND_CALL SND_fn_iInitSxd(SND_tdstInitStruct *pInitStruct)
{
    int ret;
#if defined(USE_VIRTUAL_VOICES_FOR_WAV) || !defined(DISABLE_ADPCM)
	ptr_virtualfunction virtualfunctions;
#endif
 
#if defined(_DLL_COMPILATION_MODE)
    SND_DllInitEntryPoints_StaticFunctions((HMODULE)pInitStruct->hProcessInstance );
#ifndef DISABLE_MPEG
	SND_DllInitEntryPoints_MpegFunctions(SND_hMpegModule);
#endif
#ifndef DISABLE_ADPCM
	SND_DllInitEntryPoints_AdpcmFunctions(SND_hAdpcmModule);
#endif
#ifndef DISABLE_RECORD
	SND_DllInitEntryPoints_RecordFunctions(SND_hRecordModule);
#endif
	SND_DllInitEntryPoints_DbgFunctions(SND_hDbgModule);
#endif
 
	g_iNbMicrosSxd=0;
    SNDLST2_M_DynamicInitAnchor(&micros_sxd.pList);
    SNDLST2_M_DynamicInitAnchor(&samples_sxd.pList);
 
    if ((ret=SND_fn_iInitSxdWave(pInitStruct))==C_INIT_OK)
	{
#ifndef DISABLE_SNDSTRM
	    SND_fn_iInitSxdStream(pInitStruct);
#endif /*DISABLE_SNDSTRM*/
#ifndef DISABLE_MPEG
		SND_fn_iInitMPEG(pInitStruct);
#endif
#ifndef DISABLE_ADPCM
		SND_fn_iInitSxdADPCM(pInitStruct);
#endif
#ifndef DISABLE_THEME_WAVE
		SND_fn_iInitTransitionSxdWave(pInitStruct);
#endif
	}
    
#ifdef USE_VIRTUAL_VOICES_FOR_WAV
	virtualfunctions.pfn_lPlaySxd=SND_fn_lPlaySxdWave;
	virtualfunctions.pfn_vStopSxd=SND_fn_vStopSxdWave;
	virtualfunctions.pfn_bSetParamSxd=SND_fn_bSetParamSxdWave;
	virtualfunctions.pfn_vPauseSxd=SND_fn_vPauseSxdWave;
	virtualfunctions.pfn_vResumeSxd=SND_fn_vResumeSxdWave;
	virtualfunctions.pfn_rGetPosSxd=SND_fn_rGetPosSxdWave;
	virtualfunctions.pfn_rGetLengthSxd=SND_fn_rGetLengthSxdWave;
	virtualfunctions.pfn_vRemoveCallbackSxd=SND_fn_vRemoveCallbackSxdWave;
	virtualfunctions.pfn_bTestIsPlayingSxd=SND_fn_bTestIsPlayingSxdWave;
 
	hWAVVirtModule=SND_fn_lInitSxdVirtual(SND_fn_lGetNbVoiceWishedSxdWave(),&virtualfunctions);
	#ifdef SUPERVISATER
	dbgSND_fn_vInitListesSxdVirtual((long)hWAVVirtModule,"Virtual voice for WAV");
	#endif
#endif
#ifndef DISABLE_ADPCM
	virtualfunctions.pfn_lPlaySxd=SND_fn_lPlaySxdADPCM;
	virtualfunctions.pfn_vStopSxd=SND_fn_vStopSxdADPCM;
	virtualfunctions.pfn_bSetParamSxd=SND_fn_bSetParamSxdADPCM;
	virtualfunctions.pfn_vPauseSxd=SND_fn_vPauseSxdADPCM;
	virtualfunctions.pfn_vResumeSxd=SND_fn_vResumeSxdADPCM;
	virtualfunctions.pfn_rGetPosSxd=SND_fn_rGetPosSxdADPCM;
	virtualfunctions.pfn_rGetLengthSxd=SND_fn_rGetLengthSxdADPCM;
	virtualfunctions.pfn_vRemoveCallbackSxd=SND_fn_vRemoveCallbackSxdADPCM;
	virtualfunctions.pfn_bTestIsPlayingSxd=SND_fn_bTestIsPlayingSxdADPCM;
 
	hADPCMVirtModule=SND_fn_lInitSxdVirtual(SND_fn_lGetNbVoiceWishedSxdADPCM(),&virtualfunctions);
	#ifdef SUPERVISATER
	dbgSND_fn_vInitListesSxdVirtual((long)hADPCMVirtModule,"Virtual voice for ADPCM");
	#endif
#endif
 
    return ret;
}
 
SndBool SND_CALL SND_fn_bTestInitSxd(void)
{
	return SND_fn_bTestInitSxdWave();
}
 
void SND_CALL SND_fn_vDesInitSxd(void)
{
#ifndef DISABLE_ADPCM
	SND_fn_vDesInitSxdVirtual(hADPCMVirtModule);
#endif
#ifdef USE_VIRTUAL_VOICES_FOR_WAV
	SND_fn_vDesInitSxdVirtual(hWAVVirtModule);
#endif
 
#ifndef DISABLE_ADPCM
    SND_fn_vDesInitSxdADPCM();
#endif
#ifndef DISABLE_MPEG
    SND_fn_vDesInitMPEG();
#endif
#ifndef DISABLE_SNDSTRM
    SND_fn_vDesInitSxdStream();
#endif /*DISABLE_SNDSTRM*/
    SND_fn_vDesInitSxdWave();
}
 
void SND_CALL SND_fn_vChangeNbVoiceWishedSxd()
{
}
 
void SND_CALL SND_fn_vSetEffectSxd(long num)
{
	SND_fn_vSetEffectSxdWave(num);
}
 
/*------------------------------------------------------------*/
/*      SetDopplerFactorSxd:change Doppler effect range*/
/*      Entree:new factor for Doppler effect (1.0=normal effect=physicallly realistic*/
/*				0.0=no doppler effect*/
/*      Sortie:neant*/
/*------------------------------------------------------------*/
void SND_CALL SND_fn_vSetDopplerFactorSxd(SndReal factor)
{
	SND_fn_vSetDopplerFactorSxdWave(factor);
}
 
 
/*---------------------------------------------------*/
/*	CreateMicroSxd:creer un nouveau micro*/
/*	Entrees:par=parametres du micro*/
/*	Sortie:id du micro*/
/*---------------------------------------------------*/
long SND_CALL SND_fn_lCreateMicroSxd(MicroParam* par)
{
    p_micro_description pMicro;
 
    pMicro=SND_fn_pvMallocSndEx(E_ucSndBlockMain,sizeof(micro_description));
    SNDLST2_M_DynamicInitElement(pMicro);
 
    SNDLST2_M_DynamicAddTail(&micros_sxd.pList,pMicro);
 
	if (par==NULL)
	{
		pMicro->just_created=TRUE;
	}
	else
	{
		memcpy(&pMicro->pos,&par->pos,sizeof(SndVector));
		memcpy(&pMicro->vit,&par->vit,sizeof(SndVector));
		memcpy(&pMicro->dir_nor,&par->dirnor,sizeof(SndVector));
		memcpy(&pMicro->dir_tan,&par->dirtan,sizeof(SndVector));
	}
 
    g_iNbMicrosSxd++;
 
    SND_fn_vCreateMicroSxdWave(par,(long)pMicro);
 
    return (long)pMicro;
}
 
/*---------------------------------------------------*/
/*	SetMicroParamSxd:changer les parametres d'un micro*/
/*	Entrees:sxdId=id du micro concerne*/
/*		par=nouveaux parametres du micro*/
/*	Sortie:neant*/
/*---------------------------------------------------*/
void SND_CALL SND_fn_vSetMicroParamSxd(long sxdId,MicroParam* par)
{
    p_micro_description pMicro;
    int i;
 
    SNDLST2_M_DynamicForEachElementOf(&micros_sxd.pList,pMicro,i)
    {
        if ((long)pMicro==sxdId) break;
    }
    if (pMicro!=NULL)
	{
		pMicro->just_created=FALSE;
		memcpy(&pMicro->pos,&par->pos,sizeof(SndVector));
		memcpy(&pMicro->vit,&par->vit,sizeof(SndVector));
		memcpy(&pMicro->dir_nor,&par->dirnor,sizeof(SndVector));
		memcpy(&pMicro->dir_tan,&par->dirtan,sizeof(SndVector));
	}
 
    SND_fn_vSetMicroParamSxdWave(sxdId,par);
}
 
/*--------------------------------------------------*/
/*	DestroyMicroSxd:detruire un micro*/
/*	Entree:sxdId=id du micro concerne*/
/*	Sortie:neant*/
/*--------------------------------------------------*/
void SND_CALL SND_fn_vDestroyMicroSxd(long sxdId)
{
    p_micro_description pMicro=(p_micro_description)sxdId;
 
    if (pMicro!=NULL)
    {
        SNDLST2_M_DynamicIsolate(pMicro);
        SND_fn_vFreeSndEx(E_ucSndBlockMain,pMicro);  
        g_iNbMicrosSxd--;
    }
    
    SND_fn_vDestroyMicroSxdWave(sxdId);
}
 
#ifndef DISABLE_BUFFER_CLIENT
/*----------------------------------------------------------------------*/
/*  Gestion des buffers clients*/
/*----------------------------------------------------------------------*/
long SND_CALL SND_fn_lCreateNewBufferSxd(unsigned long nb_samples,unsigned short uwResolution,unsigned short uwNbChannels,unsigned long ulFreq,SoundParam* par,td_pfn_vRefreshBufferClient callback,long user_id)
{
	SND_tdstFormat format;
	SND_tdstCallback Callback;
 
	/*Fonction obsolete !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
	snd_assert(FALSE);
	/*Fonction obsolete !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
 
	memset(&format,0,sizeof(format));
	format.eZip=SAMPLE_PCM;
	format.uFormat.stPCM.ulNbSamples=nb_samples;	
	format.uFormat.stPCM.uwResolution=uwResolution;	
	format.uFormat.stPCM.uwNbChannels=uwNbChannels;	
	format.uFormat.stPCM.ulFreq=ulFreq;
 
	memset(&Callback,0,sizeof(Callback));
	Callback.eType=BUFFER_ASYNCHRONE;
	Callback.uCallback.CallbackASynchrone=callback;
 
    return SND_fn_lCreateNewBufferExSxd(&format,&Callback,par,user_id);
}
 
void SND_CALL SND_fn_vSetParamBufferSxd(long id_buffer,SoundParam *par)
{
	pCLIENT_BUFFER pClientBuffer;
 
	if (id_buffer!=C_PLAY_FAILED)
	{
		pClientBuffer=(pCLIENT_BUFFER)id_buffer;
 
		if (pClientBuffer->eType==BUFFER_STACK)
			SetParamBufferStack(pClientBuffer->lId,par);
		else
			SND_fn_vSetParamBufferSxdWave(pClientBuffer->lId,par);
	}
}
 
void SND_CALL SND_fn_vDeleteBufferSxd(long id_buffer)
{
	pCLIENT_BUFFER pClientBuffer;
 
	if (id_buffer!=C_PLAY_FAILED)
	{
		pClientBuffer=(pCLIENT_BUFFER)id_buffer;
 
		if (pClientBuffer->eType==BUFFER_STACK)
			DeleteBufferStack(pClientBuffer->lId);
		else
			SND_fn_vDeleteBufferSxdWave(pClientBuffer->lId);
	}
}
 
void SND_CALL SND_fn_vPauseBufferSxd(long id_buffer)
{
	pCLIENT_BUFFER pClientBuffer;
 
	if (id_buffer!=C_PLAY_FAILED)
	{
		pClientBuffer=(pCLIENT_BUFFER)id_buffer;
 
		if (pClientBuffer->eType==BUFFER_STACK)
			PauseBufferStack(pClientBuffer->lId);
		else
			SND_fn_vPauseBufferSxdWave(pClientBuffer->lId);
	}
}
 
void SND_CALL SND_fn_vResumeBufferSxd(long id_buffer)
{
	pCLIENT_BUFFER pClientBuffer;
 
	if (id_buffer!=C_PLAY_FAILED)
	{
		pClientBuffer=(pCLIENT_BUFFER)id_buffer;
 
		if (pClientBuffer->eType==BUFFER_STACK)
			ResumeBufferStack(pClientBuffer->lId);
		else
			SND_fn_vResumeBufferSxdWave(pClientBuffer->lId);
	}
}
 
void* SND_CALL SND_fn_pvGetPtrBufferSxd(long id_buffer)
{
	pCLIENT_BUFFER pClientBuffer;
 
	if (id_buffer!=C_PLAY_FAILED)
	{
		pClientBuffer=(pCLIENT_BUFFER)id_buffer;
 
		if (pClientBuffer->eType==BUFFER_STACK)
			return NULL;
		else
			return SND_fn_pvGetPtrBufferSxdWave(pClientBuffer->lId);
	}
	else
		return NULL;
}
 
SndReal	SND_CALL SND_fn_rGetPosBufferSxd(long id_buffer)
{
	pCLIENT_BUFFER pClientBuffer;
 
	if (id_buffer!=C_PLAY_FAILED)
	{
		pClientBuffer=(pCLIENT_BUFFER)id_buffer;
 
		if (pClientBuffer->eType==BUFFER_STACK)
			return GetPosBufferStack(pClientBuffer->lId);
		else
			return SND_fn_rGetPosBufferSxdWave(pClientBuffer->lId);
	}
	else
		return SND_C_POS_UNKNOWN;
}
 
/**********************************************************
*	SND_fn_lCreateNewBufferExSxd=creation d'un buffer client
*	Entrees:pformat=description du format souhaite
*		pCallback=typed de callback suohaite
*		par=parametres au lancement
*		user_id=user_id
*	Retour:handle du buffer client
**************************************************************/
long SND_CALL SND_fn_lCreateNewBufferExSxd(SND_tdstFormat* pformat,SND_tdstCallback* pCallback,SoundParam* par,long user_id)
{
	pCLIENT_BUFFER pClientBuffer;
	long	lId;
 
	if (pformat->eZip==SAMPLE_PCM)
	{
		if (pCallback->eType==BUFFER_STACK)
			lId=CreateNewBufferStack(pformat,pCallback,par,user_id);
		else
			lId=SND_fn_lCreateNewBufferExSxdWave(pformat,pCallback,par,user_id);
	}
	else
	{
		SND_M_DisplayError(E_uwSndInvalidTypeOfResource,"BufferClient must be in PCM format.");
		lId=C_PLAY_FAILED;
	}
 
	if (lId!=C_PLAY_FAILED)
	{
		pClientBuffer=SND_fn_pvMallocSndEx(E_ucSndBlockMain,sizeof(CLIENT_BUFFER));
		SNDLST2_M_DynamicInitElement(pClientBuffer);
		pClientBuffer->eType=pCallback->eType;
		pClientBuffer->lId=lId;
 
		return (long)pClientBuffer;
	}
	else
		return C_PLAY_FAILED;
}
 
/*retourne le nombre de SAMPLES joues depuis la creation du buffer*/
long SND_CALL SND_fn_lGetPosBufferExSxd(long id_buffer)
{
	pCLIENT_BUFFER pClientBuffer;
 
	if (id_buffer!=C_PLAY_FAILED)
	{
		pClientBuffer=(pCLIENT_BUFFER)id_buffer;
 
		if (pClientBuffer->eType==BUFFER_STACK)
			return GetPosBufferStackEx(pClientBuffer->lId);
		else
			return SND_fn_lGetPosBufferExSxdWave(pClientBuffer->lId);
	}
	else
		return SND_C_POS_UNKNOWN;
}
 
long SND_CALL SND_fn_lPushBufferExSxd(long id_buffer,SND_tdstStackBuffer* pStack)
{
	pCLIENT_BUFFER pClientBuffer;
 
	if (id_buffer!=C_PLAY_FAILED)
	{
		pClientBuffer=(pCLIENT_BUFFER)id_buffer;
		snd_assert(pClientBuffer->eType==BUFFER_STACK);
		return PushBufferStack(pClientBuffer->lId,pStack);
	}
	else
		return C_PLAY_FAILED;
}
 
#endif /* DISABLE_BUFFER_CLIENT*/
/*-------THEME*/
typedef struct {
    tdeTypeZip	eZip;
    long		lVoice;
} transition;
 
#ifndef DISABLE_THEME_WAVE
 
/*OBSOLETE*/
long SND_CALL SND_fn_lPlayTransitionSxd(tduRefRes FirstRes,tduRefRes NextRes,SND_td_pfn_vSoundCallback transition_callback,SoundParam* par)
{
	snd_assert(FALSE);
	return C_PLAY_FAILED;
}
 
/*--------------------------------------------------------------------------------
PlayTransition:lance une melodie dynamique (suite continue de samples s'enchainant
Entrees:FirstRes=1° ressource à jouee immediatement
    NextRes=ressource devant s'enchainer à la fin de la 1° sauf contre-ordre par SetNextTrtansition
    callback=fonction a appeler chaque fois qu'une tranistion à lieu (c.a.d. qu'en on vodrait
        savoir quel sera le prochain element à jouee apres celui qui vient d'etre lance)
Sortie:ID de la voie (pour les fonctions suivantes)
-------------------------------------------------------------------------------------*/
long SND_CALL SND_fn_lPlayTransitionExSxd(tduRefRes FirstRes,tduRefRes NextRes,SND_td_pfn_vSoundCallback transition_callback,long param_callback,SoundParam* par)
{
    transition *p_trans;
#ifndef DISABLE_MPEG
	SampleParam Par2D,*ptr_Par2D;
#endif
 
    p_trans=SND_fn_pvMallocSndEx(E_ucSndBlockMain,sizeof(transition));
	switch (FirstRes.pstPtr->uRes.stSample.eZip)
	{
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
        p_trans->lVoice=SND_fn_lPlayTransitionSxdADPCM(FirstRes,NextRes,transition_callback,param_callback,par);
        p_trans->eZip=FirstRes.pstPtr->uRes.stSample.eZip;
		break;
#endif
	case SAMPLE_PCM:
        p_trans->lVoice=SND_fn_lPlayTransitionSxdWave(FirstRes,NextRes,transition_callback,param_callback,par);
        p_trans->eZip=FirstRes.pstPtr->uRes.stSample.eZip;
		break;
#ifndef DISABLE_MPEG
	case SAMPLE_MPEG:
		if (par==NULL)
			ptr_Par2D=NULL;
		else
		{
    		SND_fn_vParam3Dto2D(par,&Par2D);
			ptr_Par2D=&Par2D;
		}
        p_trans->lVoice=SND_fn_lPlayTransitionMPEG(FirstRes,NextRes,transition_callback,param_callback,ptr_Par2D);
        p_trans->eZip=FirstRes.pstPtr->uRes.stSample.eZip;
		break;
#endif
	default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
        p_trans->lVoice=C_PLAY_FAILED;
		break;
	}
 
    if (p_trans->lVoice!=C_PLAY_FAILED)
        return (long)p_trans;
    SND_fn_vFreeSndEx(E_ucSndBlockMain,p_trans);
    return C_PLAY_FAILED;
}
 
SndBool SND_CALL SND_fn_bSetParamTransitionSxd(long voice,SoundParam* par)
{
#ifndef DISABLE_MPEG
	SampleParam Par2D,*ptr_Par2D;
#endif
 
    switch (((transition*)voice)->eZip)
	{
#ifndef DISABLE_MPEG
	case SAMPLE_MPEG:
		if (par==NULL)
			ptr_Par2D=NULL;
		else
		{
    		SND_fn_vParam3Dto2D(par,&Par2D);
			ptr_Par2D=&Par2D;
		}
        return SND_fn_bSetParamTransitionMPEG(((transition*)voice)->lVoice,ptr_Par2D);
#endif
	case SAMPLE_PCM:
        return SND_fn_bSetParamTransitionSxdWave(((transition*)voice)->lVoice,par);
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
        return SND_fn_bSetParamTransitionSxdADPCM(((transition*)voice)->lVoice,par);
#endif
	default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
		return FALSE;
	}
}
 
/*--------------------------------------------------------------------------------
SetNextTransition:Modifie la ressource devant s’enchainer à la fin de la ressource en cours de restitution ; l’effet de cette fonction ne se fera donc sentir qu’à la fin de la ressource courante. De plus, si plusieurs appels ont lieu durant la restitution de la meme ressource, le dernier annule les effets des precedents.
Entrees:voice=voie concernee par la remise à jour
    new_res=nouvelle ressource à lancer par defaut à la fin de celle en cours
Retour:TRUE si OK, FALSE si voie morte (plus d'autre SetNextTransition necessaire)
-----------------------------------------------------------------------------------*/
SndBool SND_CALL SND_fn_bSetNextTransitionSxd(long voice,tduRefRes new_res)
{
	switch (((transition*)voice)->eZip)
	{
#ifndef DISABLE_MPEG
	case SAMPLE_MPEG:
        return SND_fn_bSetNextTransitionMPEG(((transition*)voice)->lVoice,new_res);
#endif
	case SAMPLE_PCM:
        return SND_fn_bSetNextTransitionSxdWave(((transition*)voice)->lVoice,new_res);
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
        return SND_fn_bSetNextTransitionSxdADPCM(((transition*)voice)->lVoice,new_res);
#endif
	default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
		return FALSE;
	}
}
 
SndBool SND_CALL SND_fn_bDoTransitionWithFadeSxd(long voice,tduRefRes new_res)
{
	switch(((transition*)voice)->eZip)
	{
#ifndef DISABLE_MPEG
	case SAMPLE_MPEG:
        return SND_fn_bDoTransitionWithFadeMPEG(((transition*)voice)->lVoice,new_res);
#endif
	case SAMPLE_PCM:
        return SND_fn_bDoTransitionWithFadeSxdWave(((transition*)voice)->lVoice,new_res);
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
        return SND_fn_bDoTransitionWithFadeSxdADPCM(((transition*)voice)->lVoice,new_res);
#endif
	default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
		return FALSE;
	}
}
 
SndBool SND_CALL SND_fn_bDoTransitionWithFadeSxd2( long voice, tduRefRes new_res, SndReal rDuration )
{
	register transition* pstVoice;

	pstVoice = (transition*)voice;
	switch( pstVoice->eZip ) {
#ifndef DISABLE_MPEG
	case SAMPLE_MPEG:
        return SND_fn_bDoTransitionWithFadeMPEG2( pstVoice->lVoice, new_res, rDuration );
#endif
	case SAMPLE_PCM:
        return SND_fn_bDoTransitionWithFadeSxdWave2( pstVoice->lVoice, new_res, rDuration );
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
        return SND_fn_bDoTransitionWithFadeSxdADPCM2( pstVoice->lVoice, new_res, rDuration );
#endif
	default:
        SND_M_DisplayError( E_uwSndInvalidStaticParamForResource, "" );
		return FALSE;
	}
}
 
/*--------------------------------------------------------------------------------
StopTransition:Stop une melodie/theme en cours
Entrees:voice=voie devant etre stoppee
-----------------------------------------------------------------------------------*/
void SND_CALL SND_fn_vStopTransitionSxd(long voice)
{
	switch(((transition*)voice)->eZip)
	{
#ifndef DISABLE_MPEG
	case SAMPLE_MPEG:
        SND_fn_vStopTransitionMPEG(((transition*)voice)->lVoice);
		break;
#endif
	case SAMPLE_PCM:
        SND_fn_vStopTransitionSxdWave(((transition*)voice)->lVoice);
		break;
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
        SND_fn_vStopTransitionSxdADPCM(((transition*)voice)->lVoice);
		break;
#endif
	default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
		break;
	}
}
 
void SND_CALL SND_fn_vPauseTransitionSxd(long voice)
{
	switch(((transition*)voice)->eZip)
	{
#ifndef DISABLE_MPEG
	case SAMPLE_MPEG:
        SND_fn_vPauseTransitionMPEG(((transition*)voice)->lVoice);
		break;
#endif
	case SAMPLE_PCM:
        SND_fn_vPauseTransitionSxdWave(((transition*)voice)->lVoice);
		break;
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
        SND_fn_vPauseTransitionSxdADPCM(((transition*)voice)->lVoice);
		break;
#endif
	default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
		break;
	}
}
 
void SND_CALL SND_fn_vResumeTransitionSxd(long voice)
{
	switch(((transition*)voice)->eZip)
	{
#ifndef DISABLE_MPEG
	case SAMPLE_MPEG:
        SND_fn_vResumeTransitionMPEG(((transition*)voice)->lVoice);
		break;
#endif
	case SAMPLE_PCM:
        SND_fn_vResumeTransitionSxdWave(((transition*)voice)->lVoice);
		break;
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
        SND_fn_vResumeTransitionSxdADPCM(((transition*)voice)->lVoice);
		break;
#endif
	default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
		break;
	}
}
#endif /* DISABLE_THEME_WAVE*/
 
 
/*--------------------------------------------------
relache-reprise a chaud des drives
---------------------------------------------------------*/
void SND_CALL SND_fn_vReleaseDriverSxd(void)
{	
#ifndef DISABLE_MPEG
	SND_fn_vReleaseDriverMPEG();
#endif
#ifndef DISABLE_ADPCM
	SND_fn_vReleaseDriverSxdADPCM();
#endif
	SND_fn_vReleaseDriverSxdWave();
}
 
void SND_CALL SND_fn_vRestoreDriverSxd(void)
{
	SND_fn_vRestoreDriverSxdWave();
#ifndef DISABLE_ADPCM
	SND_fn_vRestoreDriverSxdADPCM();
#endif
#ifndef DISABLE_MPEG
	SND_fn_vRestoreDriverMPEG();
#endif
}
 
void SND_CALL SND_fn_vForceReleaseDriverSxd(void)
{	
	SND_fn_vForceReleaseDriverSxdWave();
}
 
void SND_CALL SND_fn_vForceRestoreDriverSxd(void)
{
	SND_fn_vForceRestoreDriverSxdWave();
}
 
/*---------------------------------------------------------*/
/*	GetTargetLabel: retourne le label designant la tareget*/
/*	Entree: name=nom cible*/
/*		nb_char=taille maxi de la cible*/
/*----------------------------------------------------------*/
void SND_CALL SND_fn_vGetTargetLabelSxd(char* name,int nb_char)
{
	SND_fn_vGetTargetLabelSxdWave(name,nb_char);
}
 
void SND_CALL SND_fn_vSetupTargetSxd(void)
{
	SND_fn_vSetupTargetSxdWave();
}
 
SndBool SND_CALL SND_fn_bCanSetupTargetSxd(void)
{
	return SND_fn_bCanSetupTargetSxdWave();
}
 
/*-------------------------------------------------*/
/* Fonction de synchro moteur*/
/*-------------------------------------------------*/
void SND_CALL SND_fn_vSynchroSxd()
{
#ifndef DISABLE_ADPCM
	SND_fn_vSynchroSxdVirtual(hADPCMVirtModule);
#endif
#ifdef USE_VIRTUAL_VOICES_FOR_WAV
	SND_fn_vSynchroSxdVirtual(hWAVVirtModule);
#endif
	SND_fn_vSynchroSxdWave();
}
 
 
/*fonctions OBSOLETEs à garder pour compatibilte*/
int SND_CALL SND_fn_iInitBnkSxd(long num)
{
	return C_INIT_FAILED;
}
 
SndBool	SND_CALL SND_fn_bTestInitBnkSxd(long num)
{
	return FALSE;
}
 
void SND_CALL SND_fn_vDesInitBnkSxd(long num)
{
}
 
void SND_CALL SND_fn_vDesInitAllBnkSxd(void)
{
}
 
void SND_CALL SND_fn_vSetDefaultRollOffSxd(RollOffParam* rolloff)
{
	SND_fn_vSetDefaultRollOffSxdWave(rolloff);
#ifndef DISABLE_MPEG
	SND_fn_vSetDefaultRollOffMPEG(rolloff);
#endif
#ifndef DISABLE_ADPCM
	SND_fn_vSetDefaultRollOffSxdADPCM(rolloff);
#endif
}
 
 
#ifndef DISABLE_BUFFER_CLIENT
/*--------------------------------------*/
/* data-Buffers stacks (empiles par appel à PuchBufferStack)*/
typedef struct BUFFER_PUSHED_ *pBUFFER_PUSHED;
 
SNDLST2_M_DynamicUseListOf(pBUFFER_PUSHED);
 
typedef struct BUFFER_PUSHED_{
	void*			ptrData;
	unsigned long	ulNbSamples;
	void*			ptrCurrentData;
	unsigned long	ulSampleLeft;
	long			lId;
	SndBool			bValid;
	SNDLST2_M_DynamicElementDeclaration(pBUFFER_PUSHED)
} BUFFER_PUSHED;
 
typedef struct LIST_BUFFER_PUSHED_{
                SNDLST2_M_DynamicAnchorDeclaration(pBUFFER_PUSHED) pList;
} LISTE_BUFFER_PUSHED;
 
/*description d'un buffer client stack*/
typedef struct {
	long				lIdBufferSynchrone;
	SND_tdstFormat		stFormat;
	SND_tdstCallback	stCallback;
	long				lUserId;
    SNDLST2_M_DynamicAnchorDeclaration(pBUFFER_PUSHED) pBufferList;
	long				lSampleToBytesShift;
	long				lNbSampleSent;
} stBufferStack;
 
long g_lPushedBufferId=0;
 
/*fonction de callback client du buffer asynchrone utilise par le buffer stack*/
void SND_CALL fnRefreshBufferStack(long user_id,unsigned long first,unsigned long nb,void* ptr_first_sample)
{
	stBufferStack	*pstBufferStack;
	pBUFFER_PUSHED	pstPushedBuffer;
	unsigned long	nb_samples_left,nb_to_copy;
	void			*current_ptr;
 
	pstBufferStack=(stBufferStack*)user_id;
	pstPushedBuffer=SNDLST2_M_DynamicGetFirstElement(&pstBufferStack->pBufferList);
 
	if (pstPushedBuffer && pstPushedBuffer->bValid)
	{
		nb_samples_left=nb;
		current_ptr=ptr_first_sample;
 
		while (nb_samples_left>0)
		{
			nb_to_copy=min(pstPushedBuffer->ulSampleLeft,nb_samples_left);
			memcpy(current_ptr,pstPushedBuffer->ptrCurrentData,nb_to_copy<<pstBufferStack->lSampleToBytesShift);
 
			pstPushedBuffer->ptrCurrentData=(void*)((unsigned long)pstPushedBuffer->ptrCurrentData+(nb_to_copy<<pstBufferStack->lSampleToBytesShift));
			current_ptr=(void*)((unsigned long)current_ptr+(nb_to_copy<<pstBufferStack->lSampleToBytesShift));
			pstPushedBuffer->ulSampleLeft-=nb_to_copy;
			nb_samples_left-=nb_to_copy;
 
			if (pstPushedBuffer->ulSampleLeft<=0)
			{/*next buffer*/
				/*callback stack*/
				(*pstBufferStack->stCallback.uCallback.CallbackStack)(pstBufferStack->lUserId,pstPushedBuffer->lId);
				/*destruction de lancien data-buffer*/
				SNDLST2_M_DynamicIsolate(pstPushedBuffer);
				SND_fn_vFreeSndEx(E_ucSndBlockMain,pstPushedBuffer);
				/*passage au data-buffer suivant*/
				pstPushedBuffer=SNDLST2_M_DynamicGetFirstElement(&pstBufferStack->pBufferList);
 
				if (!pstPushedBuffer)
				{/*on comble avec du silence*/
					memset(current_ptr,0,nb_samples_left<<pstBufferStack->lSampleToBytesShift);
					nb_samples_left=0;
				}
			}
		}
	}
	else
	{/*plus de buffers en stack*/
		memset(ptr_first_sample,0,nb<<pstBufferStack->lSampleToBytesShift);
	}
 
	pstBufferStack->lNbSampleSent+=nb;
}
 
/*creation d'un nouveau buffer stack*/
long CreateNewBufferStack(SND_tdstFormat* pformat,SND_tdstCallback* pCallback,SoundParam* par,long user_id)
{
	stBufferStack *pstBuffer;
	SND_tdstCallback	stCallback;
 
	/*pas de choix offert sur la taille du buffer client stack*/
	snd_assert(pformat->uFormat.stPCM.ulNbSamples==0);
 
	pstBuffer=SND_fn_pvMallocSndEx(E_ucSndBlockMain,sizeof(stBufferStack));
	memcpy(&pstBuffer->stFormat,pformat,sizeof(SND_tdstFormat));
	memcpy(&pstBuffer->stCallback,pCallback,sizeof(SND_tdstCallback));
	pstBuffer->lUserId=user_id;
	pstBuffer->lSampleToBytesShift=pformat->uFormat.stPCM.uwResolution/8+pformat->uFormat.stPCM.uwNbChannels-2;
	SNDLST2_M_DynamicInitAnchor(&pstBuffer->pBufferList);
	pstBuffer->lNbSampleSent=0;
 
	/*creation du buffer asynchrone squatte par le buffer stack*/
	stCallback.eType=BUFFER_SYNCHRONE;
	stCallback.uCallback.CallbackSynchrone=fnRefreshBufferStack;
	stCallback.uInfo.lNbSampleToPush=0;
 
	pstBuffer->lIdBufferSynchrone=SND_fn_lCreateNewBufferExSxd(
		&pstBuffer->stFormat
		,&stCallback
		,par
		,(long)pstBuffer);
 
	/*bufferstack identifie par son pstBuffer*/
	return (long)pstBuffer;
}
 
/*temps ecoule depuis la creation du buffer client (en Sec, SndReal)*/
SndReal GetPosBufferStack(long id_buffer)
{
	stBufferStack	*pstBufferStack;
	long			nb_samples;
	double			temps;
 
	pstBufferStack=(stBufferStack*)id_buffer;
 
	nb_samples=GetPosBufferStackEx(id_buffer);
	temps=(double)nb_samples/pstBufferStack->stFormat.uFormat.stPCM.ulFreq;
	
	if ((int)temps<M_HighestIntAbsValueRealSnd)
		return M_DoubleToRealSnd(temps);
	else
		return SND_C_POS_UNKNOWN;
}
 
/*push d'un data-buffer dans le stackbuffer-client*/
/*	retourne l'id du buffer (parametre de la fonction de callback)*/
long PushBufferStack(long id_buffer,SND_tdstStackBuffer* pStack)
{
	stBufferStack	*pstBufferStack;
	pBUFFER_PUSHED	pstPushedBuffer;
 
	pstBufferStack=(stBufferStack*)id_buffer;
	pstPushedBuffer=SND_fn_pvMallocSndEx(E_ucSndBlockMain,sizeof(BUFFER_PUSHED));
    SNDLST2_M_DynamicInitElement(pstPushedBuffer);
	pstPushedBuffer->ptrData=pStack->ptrData;
	pstPushedBuffer->ulNbSamples=pStack->ulNbSamples;
	pstPushedBuffer->ptrCurrentData=pstPushedBuffer->ptrData;
	pstPushedBuffer->ulSampleLeft=pstPushedBuffer->ulNbSamples;
	pstPushedBuffer->bValid=FALSE;
	pstPushedBuffer->lId=g_lPushedBufferId++;
	if (g_lPushedBufferId>=0x7fffffff)
		g_lPushedBufferId=0;
 
    SNDLST2_M_DynamicAddTail(&pstBufferStack->pBufferList,pstPushedBuffer);
 
	pstPushedBuffer->bValid=TRUE;
 
	return pstPushedBuffer->lId;
}
 
void SetParamBufferStack(long id_buffer,SoundParam *par)
{
	stBufferStack	*pstBufferStack;
 
	pstBufferStack=(stBufferStack*)id_buffer;
	SND_fn_vSetParamBufferSxd(pstBufferStack->lIdBufferSynchrone,par);
}
 
void DeleteBufferStack(long id_buffer)
{
	stBufferStack	*pstBufferStack;
	pBUFFER_PUSHED	pstPushedBuffer,pstPushedBufferNext;
	int i;
 
	pstBufferStack=(stBufferStack*)id_buffer;
 
	/*arret du buffer synchrone associe -> plus de callback*/
	SND_fn_vDeleteBufferSxd(pstBufferStack->lIdBufferSynchrone);
 
	/*nettoyage*/
	SNDLST2_M_DynamicForEachMovingElementOf(&pstBufferStack->pBufferList,pstPushedBuffer,pstPushedBufferNext,i)
	{
		SNDLST2_M_DynamicIsolate(pstPushedBuffer);
		SND_fn_vFreeSndEx(E_ucSndBlockMain,pstPushedBuffer);
	}
	SND_fn_vFreeSndEx(E_ucSndBlockMain,pstBufferStack);
}
 
void PauseBufferStack(long id_buffer)
{
	stBufferStack	*pstBufferStack;
 
	pstBufferStack=(stBufferStack*)id_buffer;
	SND_fn_vPauseBufferSxd(pstBufferStack->lIdBufferSynchrone);
}
 
void ResumeBufferStack(long id_buffer)
{
	stBufferStack	*pstBufferStack;
 
	pstBufferStack=(stBufferStack*)id_buffer;
	SND_fn_vResumeBufferSxd(pstBufferStack->lIdBufferSynchrone);
}
 
long GetPosBufferStackEx(long id_buffer)
{
	stBufferStack	*pstBufferStack;
 
	pstBufferStack=(stBufferStack*)id_buffer;
 
	return pstBufferStack->lNbSampleSent;
}
#endif /* DISABLE_BUFFER_CLIENT*/
 
/* give the main Zip type (the only one whim nbvoicewhished can be set by user*/
tdeTypeZip fn_eMainTypeOfZip()
{
#ifndef DISABLE_ADPCM
	if (SND_fn_bIsLibActiveSxdADPCM())
		return SAMPLE_ADPCM;
	else
#endif
		return SAMPLE_PCM;
}
 
/*/////////////////////////////////////////////////////*/
/* NAME: SND_fn_vSetNbVoiceWishedSxd*/
/**/
/* ROLE: modify value for number of voices stored in INI file*/
/*		and the current value used by SNDVIRT*/
/* AUTHOR: Stephane Ronse*/
/*/////////////////////////////////////////////////////*/
void SND_CALL SND_fn_vSetNbVoiceWishedSxd(tdeTypeZip ezip,long nb)
{
	switch (ezip)
	{
	case SAMPLE_PCM:
		#ifdef USE_VIRTUAL_VOICES_FOR_WAV
		SND_fn_vChangeNbVoiceWishedSxdVirtual(hWAVVirtModule,nb);
		#endif /*USE_VIRTUAL_VOICES_FOR_WAV*/
		break;
	case SAMPLE_ADPCM:
		#ifndef DISABLE_ADPCM
		if (!SND_fn_b3DOneShootShouldBeConvertedSxdWave())
			SND_fn_vChangeNbVoiceWishedSxdVirtual(hADPCMVirtModule,nb);
		#ifdef USE_VIRTUAL_VOICES_FOR_WAV
		else
			SND_fn_vChangeNbVoiceWishedSxdVirtual(hWAVVirtModule,nb);
		#endif /*USE_VIRTUAL_VOICES_FOR_WAV*/
		#endif /*DISABLE_ADPCM*/
		break;
	default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"This Zip type doesn't manage with SNDVIRT");
		break;
	}
}
 
/*/////////////////////////////////////////////////////*/
/* NAME: SND_fn_lGetNbVoiceWishedSxdWave*/
/**/
/* ROLE: indicates what is the main format*/
/**/
/* AUTHOR: Stephane Ronse*/
/*/////////////////////////////////////////////////////*/
tdeTypeZip	SND_CALL SND_fn_eGetMainFormatSxd()
{
#ifndef DISABLE_ADPCM
	if (!SND_fn_b3DOneShootShouldBeConvertedSxdWave() && SND_fn_bIsLibActiveSxdADPCM())
		return SAMPLE_ADPCM;
	else
#endif
		return SAMPLE_PCM;
}
 
/*/////////////////////////////////////////////////////*/
/* NAME: SND_fn_lGetNbVoiceWishedSxdWave*/
/**/
/* ROLE: returns value for SNDVIRT's number of voices*/
/*       (checked value found in .ini or estimated optimal value)*/
/* AUTHOR: Stephane Ronse*/
/*/////////////////////////////////////////////////////*/
long SND_CALL SND_fn_lGetNbVoiceWishedSxd()
{
	return SND_fn_lGetNbVoiceWishedSxdWave();
}
 
/*/////////////////////////////////////////////////////*/
/* NAME: SND_fn_lGetNbVoiceOptimumSxd*/
/**/
/* ROLE: returns best value for SNDVIRT's number of voices*/
/*       (always estimated optimal value)*/
/* AUTHOR: Stephane Ronse*/
/*/////////////////////////////////////////////////////*/
long SND_CALL SND_fn_lGetNbVoiceOptimumSxd()
{
	return SND_fn_lGetNbVoiceOptimumSxdWave();
}
 
/***********************************************************************
	SND_fn_bSetResourceStaticVolumeSxd:
		change the volume for a specific resource given its Editor ID
******************************************************************************/
SndBool SND_CALL SND_fn_bSetResourceStaticVolumeSxd(tdstBlockResourceMem* pstRes,unsigned char ucVolume)
{
	SndBool ret;

    switch (pstRes->uRes.stSample.eZip)
    {
    case SAMPLE_PCM:
#ifndef DISABLE_SNDSTRM
        if (pstRes->uRes.stSample.bStream)
            ret=SND_fn_bSetResourceStaticVolumeSxdStream(pstRes,ucVolume);
        else
#endif /*DISABLE_SNDSTRM*/
            ret=SND_fn_bSetResourceStaticVolumeSxdWave(pstRes,ucVolume);
        break;
#ifndef DISABLE_MPEG
    case SAMPLE_MPEG:
        ret=SND_fn_bSetResourceStaticVolumeMPEG(pstRes,ucVolume);
        break;
#endif /*DISABLE_MPEG*/
#ifndef DISABLE_ADPCM
	case SAMPLE_ADPCM:
        ret=SND_fn_bSetResourceStaticVolumeSxdADPCM(pstRes,ucVolume);
		break;
#endif /*DISABLE_ADPCM*/
    default:
        SND_M_DisplayError(E_uwSndInvalidStaticParamForResource,"");
        ret=FALSE;
        break;
    }

	return ret;
}


