/*
//////////////////////////////////////////////////////////////
//              SOUND3D.C       Version 2.0                 //
//////////////////////////////////////////////////////////////
*/
 
#include "SNDinc.h"
#include "sndevent.h"
#include "ERM.h"
#include "sndext/errsnd.h"
#include "SND.h"
 
#ifdef DEBUG_SON
#include <stdio.h>
#endif
 
/*--external FANTOME event*/
SND_tduRefEvt SND_EVT_FANTOME={(unsigned long)EVT_FANTOME_PTR};
 
#ifndef NO_ACP_SOUND
 
#if defined(_DLL_COMPILATION_MODE)/* || defined(USE_DBG_MODULE)*/
#include "snddll.h"
#endif
 
#include "snddbg.h"
 
#include "sndthrd.h"
 
#include "sndres.h"
#include "sndplay.h"
#include "sndswtch.h"
#include "sndthrd.h"
 
#ifdef SND_SCRIPT_VERSION
#include "sndld_s.h"
#endif /*SND_SCRIPT_VERSION*/
 
 
#ifdef SND_HYBRID_VERSION
#include "sndld_hy.h"
#endif /*SND_HYBRID_VERSION*/
 
 
#include "sndini.h"
#include "sndrnd.h"
 
 
 
/*For debugging*/
char SND_g_DateVersion[]=__DATE__"-"__TIME__;	/*date of last compilation/LIB generation*/
char SND_g_LabelVersion[]=
#include "SND/version.txt"
;												/*version label (PUBLIC\SND\VESRION.TXT)*/
 
#ifdef SOUND_DEBUG
#include <stdio.h>
#endif /*SOUND_DEBUG*/
 
/*------------- internal variables---------------------------*/
/*------- associations (object <-> event) description*/
typedef struct ASSOCIATION_DESCRIPTION_ *pASSOCIATION_DESCRIPTION;
 


SNDLST2_M_DynamicUseListOf(pASSOCIATION_DESCRIPTION);
 


typedef struct ASSOCIATION_DESCRIPTION_{
				SndBool					bDynamic;	/*Update association*/
				long					channel;	/*sound channel*/
                long                    indice;     /*sound object id*/
                long                    type;       /*sound object type*/
                SND_tduRefEvt			evt;		/*sound event*/
                long                    prio;		/*priority; no used*/
                long                    voice;		/*SndPlay voice id (if any)*/
                tduRefRes               res_hi;     /*sound resource associated with sound event (if any)*/
				SndBool                 bValid;     /*FALSE when then association is no more valid*/
                SndReal                 rDeTune;    /*random Detuning parameter (0 when inactive)*/
                long                    lHandle;    /*SendRequestSound handle (returned code)(to manage Callback or GetPos)*/
				RollOffParam            stRollOff;	/*rolloff parameter*/
                SNDLST2_M_DynamicElementDeclaration(pASSOCIATION_DESCRIPTION)
} ASSOCIATION_DESCRIPTION;


 
typedef struct LISTE_ASSOCIATION_{
                SNDLST2_M_DynamicAnchorDeclaration(pASSOCIATION_DESCRIPTION) pList;
} LISTE_ASSOCIATION;
 


#define NB_ASSOCIATION_MAX 65
 

static LISTE_ASSOCIATION association;    /*description of active association*/
 
/*-------information about microphones*/
typedef struct MICRO_DESCRIPTION_ *pMICRO_DESCRIPTION;
 
SNDLST2_M_DynamicUseListOf(pMICRO_DESCRIPTION);
 

typedef struct MICRO_DESCRIPTION_{
        long    sndId;
        SNDLST2_M_DynamicElementDeclaration(pMICRO_DESCRIPTION)
}MICRO_DESCRIPTION;
 


typedef struct LISTE_MICRO_{
        SNDLST2_M_DynamicAnchorDeclaration(pMICRO_DESCRIPTION) pList;
}LISTE_MICRO;
 

static LISTE_MICRO micros_sound;/*list of the active microphones (used by SynchroSound)*/
static int g_iNbActiveMicros=0;	/*number of created/actived microphone*/
 


/*-------volume lines*/
typedef struct tdstVolumeLine_ *ptdstVolumeLine;
 

SNDLST2_M_DynamicUseListOf(ptdstVolumeLine);
 

typedef struct tdstVolumeLine_{
        long lVol;      /*current volume for the volume line*/
        SNDLST2_M_DynamicElementDeclaration(ptdstVolumeLine)
}tdstVolumeLine;
 

typedef struct LISTE_tdstVolumeLine_{
        SNDLST2_M_DynamicAnchorDeclaration(ptdstVolumeLine) pList;
}LISTE_tdstVolumeLine;
 

static LISTE_tdstVolumeLine g_VolumeLines; 
static int nb_volume_lines=0;
 

/*------ informations about sound object's volume (may be one volume for each object)*/
typedef struct tdstVolumeChanged_ *ptdstVolumeChanged;
 

SNDLST2_M_DynamicUseListOf(ptdstVolumeChanged);
 

typedef struct tdstVolumeChanged_{
        long lVolume;	/*current volume for this sound object type*/
		long lIndice;   /*sound object id*/
        SNDLST2_M_DynamicElementDeclaration(ptdstVolumeChanged)
}tdstVolumeChanged;
 
static int nb_object_type=0;
typedef struct {
        tdstAllRetObjectSound       pfnRetObjectSound;	/*callback function (to get location of this object)*/
		tdstAllRetChannelSound      pfnRetChannelSound;	/*Channel callback function (to get location of the sound)*/
        tdstVolumeLine*             pstVolumeLine;		/*volume line id associated with this type (if any)*/
		td_pfn_vCopyString          pfnInfoObject;      /*info callback function (if any)*/
        td_pfn_bRetRollOffFactor    pfnRollOff;			/*rolloff callback function (if any)*/
        SND_tdstBlockEvent*         pstLastEvent;		/*last sound event played*/
        long                        lVolume;			/*current volume*/
        SNDLST2_M_DynamicAnchorDeclaration(ptdstVolumeChanged)  pListVolumeChanged;/*list of ACTIVE objects whose volume have been changed (other object used the type's volume)*/
} tdstTypeObjectInfos;
 
static tdstTypeObjectInfos *g_d_pstTypeObjectSoundInfos;
 

static tdstAllRetMicroSound g_st_pfnRetMicroSound={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
 
 
SndReal fn_rRetObjectSoundSndRealDefault(long indice);
unsigned char fn_ucRetObjectSoundREVERBDefault(long indice);
void fn_vRetObjectSoundExtraCoefDefault(long indice,SND_tduRefEvt evt,SndReal* pitch,SndReal* pan,SndReal* vol);
long fn_lRetObjectSoundSwitchDefault(long indice,long type_switch);
SndBool fn_bRetObjectSoundMicroLinkDefault(long indice,long micro);
void fn_vRetObjectSoundVectorIDefault(long indice, SndVector * vect);
void fn_vRetObjectSoundVectorJDefault(long indice, SndVector * vect);
void fn_vRetObjectSoundVectorKDefault(long indice, SndVector * vect);
 
static tdstAllRetObjectSound g_astTypeObjectSoundInfosDefault={
	fn_rRetObjectSoundSndRealDefault,
	fn_rRetObjectSoundSndRealDefault,
	fn_rRetObjectSoundSndRealDefault,
	fn_rRetObjectSoundSndRealDefault,
	fn_rRetObjectSoundSndRealDefault,
	fn_rRetObjectSoundSndRealDefault,
	fn_ucRetObjectSoundREVERBDefault,
	fn_vRetObjectSoundExtraCoefDefault,
	fn_lRetObjectSoundSwitchDefault,
	fn_bRetObjectSoundMicroLinkDefault,
	fn_vRetObjectSoundVectorIDefault,
	fn_vRetObjectSoundVectorJDefault,
	fn_vRetObjectSoundVectorKDefault
};


SndReal fn_rRetChannelSoundSndReal0Default(long channel, long indice);
SndReal fn_rRetChannelSoundSndReal1Default(long channel, long indice);
SndBool fn_bRetChannelSoundActiveDefault(long channel, long indice);
SndBool fn_bRetChannelSoundAbsCoordDefault(long channel, long indice);

//Default callback for sound channel
static tdstAllRetChannelSound g_astChannelSoundInfosDefault = {
	fn_rRetChannelSoundSndReal0Default,
	fn_rRetChannelSoundSndReal0Default,
	fn_rRetChannelSoundSndReal0Default,
	fn_rRetChannelSoundSndReal0Default,
	fn_rRetChannelSoundSndReal0Default,
	fn_rRetChannelSoundSndReal0Default,
	fn_bRetChannelSoundActiveDefault,
	TRUE
};



/*--next value to be returned by SendRequestSound*/
static long HandleCallback=1;
 
/*--global initialization flag*/
static SndBool g_bInitDoneSound=FALSE;
 
/*--doppler activation: FALSE->no doppler effect*/
static SndBool g_bDopplerActive=TRUE;
 
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
/*		Private functions											 */
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
/*save the current event for a specific type*/
void fnSetLastEventForSoundObjectType(long type,SND_tdstBlockEvent* evt)
{
        if (type<nb_object_type && type>=0)
                g_d_pstTypeObjectSoundInfos[type].pstLastEvent=evt;
}
 
SND_tdstBlockEvent* SND_fn_pstGetLastEventForObjectTypeSound(long type)
{
        if (type<nb_object_type && type>=0)
                return g_d_pstTypeObjectSoundInfos[type].pstLastEvent;
        else
                return NULL;
}
 
 
/*------------------------------------------------------------------------------*/
/* managemnent of ChangeVolume event											*/		
/* Call to ChangevolumeType cancel any other previous call to ChangeVolueObject */
/*																				*/
/* set volume for object to 127 = retire volume object from list				*/
/*------------------------------------------------------------------------------*/
void fn_vResetVolumeForObject(long indice,long type)
{
        ptdstVolumeChanged pVol;
        int i;
		SndBool	bFound=FALSE;

        /*search for the correspondant object*/
        SNDLST2_M_DynamicForEachElementOf(&g_d_pstTypeObjectSoundInfos[type].pListVolumeChanged,pVol,i)
        {
                if (pVol->lIndice==indice)
				{
					bFound=TRUE;
                    break;
				}
        }

		if (bFound)
		{
			SNDLST2_M_DynamicIsolate(pVol);
			SND_fn_vFreeSndEx(E_ucSndBlockMain,pVol);
		}
}

/*Change volume for a sound type -> cancel all other objet volume (volume for sound type is more important)*/
void fn_vChangeVolumeForType(long type,long lNewVolume)
{
        g_d_pstTypeObjectSoundInfos[type].lVolume=lNewVolume;
}
 
void fn_vResetVolumeForType(long type)
{
        g_d_pstTypeObjectSoundInfos[type].lVolume=C_SOUNDVOL_MAXI;
}
 
/*Change volume for one object*/
void fn_vChangeVolumeForObject(long indice,long type,long lNewVolume)
{
        ptdstVolumeChanged pVol;
        int i;
		SndBool bFound=FALSE;
 
        if (lNewVolume==C_SOUNDVOL_MAXI)
        {/*reset object*/
			fn_vResetVolumeForObject(indice,type);
        }
        else
        {
                /*look if object is still in the list*/
                SNDLST2_M_DynamicForEachElementOf(&g_d_pstTypeObjectSoundInfos[type].pListVolumeChanged,pVol,i)
                {
                        if (pVol->lIndice==indice)
						{
							bFound=TRUE;
                            break;
						}
                }
 
                if (!bFound)
                {/*the object is not yet in the list*/
                        pVol=SND_fn_pvMallocSndEx(E_ucSndBlockMain,sizeof(tdstVolumeChanged));
                        SNDLST2_M_DynamicInitElement(pVol);
                        SNDLST2_M_DynamicAddTail(&g_d_pstTypeObjectSoundInfos[type].pListVolumeChanged,pVol);
                        pVol->lIndice=indice;
                }
 
                pVol->lVolume=lNewVolume;
        }
}

long fn_lGetVolumeForType(long type)
{
	return g_d_pstTypeObjectSoundInfos[type].lVolume;
}

long fn_lGetVolumeForObject(long indice,long type)
{
    ptdstVolumeChanged pVol;
    int i;
	SndBool	bFound=FALSE;

	/*first look if there is a specific volume for this object*/
	SNDLST2_M_DynamicForEachElementOf(&g_d_pstTypeObjectSoundInfos[type].pListVolumeChanged,pVol,i)
	{
			if (pVol->lIndice==indice)
			{
				bFound=TRUE;
				break;
			}
	}
	if (bFound)
		return pVol->lVolume;
	else
		return C_SOUNDVOL_MAXI;
}

/*--------------------------------------------------------*/
/*      GetMicroParam:get microphone dynamic parameters (location...)*/
/*      Parametere:id=microphone id*/
/*              par(OUT)=struct where the dynamis parameters will be copied*/
/*      Retour:neant*/
/*------------------------------------------------------*/
void GetMicroParam(long id,MicroParam *par)
{
                par->pos.x=g_st_pfnRetMicroSound.X(id);
                par->pos.y=g_st_pfnRetMicroSound.Y(id);
                par->pos.z=g_st_pfnRetMicroSound.Z(id);
                par->vit.x=g_st_pfnRetMicroSound.VX(id);
                par->vit.y=g_st_pfnRetMicroSound.VY(id);
                par->vit.z=g_st_pfnRetMicroSound.VZ(id);
                par->dirnor.x=g_st_pfnRetMicroSound.DNX(id);
                par->dirnor.y=g_st_pfnRetMicroSound.DNY(id);
                par->dirnor.z=g_st_pfnRetMicroSound.DNZ(id);
                par->dirtan.x=g_st_pfnRetMicroSound.DTX(id);
                par->dirtan.y=g_st_pfnRetMicroSound.DTY(id);
                par->dirtan.z=g_st_pfnRetMicroSound.DTZ(id);
 
				/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
                /*vector orientation MUST NOT BE NULL !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
                snd_assert((par->dirnor.x!=0)||(par->dirnor.y!=0)||(par->dirnor.z!=0));
                snd_assert((par->dirtan.x!=0)||(par->dirtan.y!=0)||(par->dirtan.z!=0));
                                if ((par->dirnor.x==0)&&(par->dirnor.y==0)&&(par->dirnor.z==0))
                                {
                                        par->dirnor.x=C_SNDREAL_1;
                                }
                if ((par->dirtan.x==0)&&(par->dirtan.y==0)&&(par->dirtan.z==0))
                                {
                                        par->dirtan.y=C_SNDREAL_1;
                                }
                /*vector orientation MUST NOT BE NULL !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
				/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
}
 
/*----------------------------------------------------------------
        get a free association 
        return the id of this free association 
-----------------------------------------------------------------*/
ASSOCIATION_DESCRIPTION* pre_associe_sound(void)
{
        pASSOCIATION_DESCRIPTION pAsso;
        int i;
 
        /*get the number of element in the list (i)*/
        i=SNDLST2_M_DynamicGetNumberOfElements(&association.pList);
        if (i>=NB_ASSOCIATION_MAX)
        {
                SND_M_DisplayErrorEx(E_uwSndTooManyEvents,"",SNDERR_DISPLAY_IF_WANTED);
                return NULL;
        }
 
        pAsso=(pASSOCIATION_DESCRIPTION)SND_fn_pvMallocSndEx(E_ucSndBlockMain,sizeof(ASSOCIATION_DESCRIPTION));
        SNDLST2_M_DynamicInitElement(pAsso);
        return pAsso;
}
 
/*---------------------------------------------------------
                delete a association
                Parameteree:association id
----------------------------------------------------------*/
void erase_association(pASSOCIATION_DESCRIPTION asso)
{
        #ifdef SUPERVISATER
        dbgSND_fn_vKillEventToObject(asso->indice,(long)asso);
        #endif
                        
        SNDLST2_M_DynamicIsolate(asso);
        SND_fn_vFreeSndEx(E_ucSndBlockMain,asso);
}
 

/*
 *=============================================================================
 *	associe_sound
 *
 *  Description : Store informations about a association
 *=============================================================================
 *  Input:	asso : association used to sotre these informations
 *			channel : sound channel id
 *			indice : sound object id
 *			type : sound object type id
 *			voice : PlaySnd voice
 * 			evt : sound event played
 *			res_hi : resource played by Playsnd
 *			rDetune : ranomd detuning parmeter
 *			lHandle  : retunred code for SendRequestSound
 *
 *  Output : None
 *
 *=============================================================================
 *  Creation date :			            Author :            
 *=============================================================================
 *  Modification date : 01/06/99	    Author : Pascal Lalancette 
 *  Modifications : Add Sound channel support
 *=============================================================================
 */
void associe_sound(pASSOCIATION_DESCRIPTION asso, long channel,long indice,long type,long prio,long voice,SND_tduRefEvt evt,tduRefRes res_hi,SndReal rDeTune,long lHandle)
{
        int i;
        pASSOCIATION_DESCRIPTION pAsso,pAssoNext;
 
        /*only one association for each vlue of "voice"*/
        SNDLST2_M_DynamicForEachMovingElementOf(&association.pList,pAsso,pAssoNext,i)
        {
                if (!(pAsso->bValid) || (pAsso->voice==voice))
                {
                        erase_association(pAsso);
                }
        }
 
		/*try to group association for the same object/type*/
		SNDLST2_M_DynamicForEachElementOf(&association.pList,pAsso,i)
		{
			if ((pAsso->indice==indice) && (pAsso->type==type))
				break;
		}
		if (pAsso)
		{
			pAssoNext=SNDLST2_M_DynamicGetNextElement(pAsso);
			SNDLST2_M_DynamicInsertBetween(asso,pAsso,pAssoNext);
		}
		else
		{
			SNDLST2_M_DynamicAddTail(&association.pList,asso);
		}
 
        asso->bDynamic=TRUE;                      
        asso->channel=channel;                      
        asso->indice=indice;                      
        asso->type=type;                          
        asso->prio=prio;                          
        asso->voice=voice;
        asso->evt=evt;
        asso->res_hi=res_hi;
        asso->bValid=TRUE;
        asso->rDeTune=rDeTune;
        asso->lHandle=lHandle;
 
        #ifdef SUPERVISATER
        dbgSND_fn_vAddEventToObject(indice,type,(long)asso,evt);
        #endif
}
 



/*
 *=============================================================================
 *	get_association_object
 *
 *  Description : Get the first association found used by a object/event couple
 *=============================================================================
 *  Input
 *			indice : sound object id
 *			type : sound object type id
 * 			evt : sound event played
 *
 *  Output
 *			asso : association pointer or NULL if not found
 *
 *=============================================================================
 *  Creation date :			            Author :            
 *=============================================================================
 *  Modification date : 01/06/99	    Author : Pascal Lalancette 
 *  Modifications : Changed name for get_association_object()
 *=============================================================================
 */
pASSOCIATION_DESCRIPTION get_association_object(long indice,long type,void* evt)
{

	pASSOCIATION_DESCRIPTION pAsso;
	int i=0;

	if (evt==NULL)
	{
		SNDLST2_M_DynamicForEachElementOf(&association.pList,pAsso,i)
		{
			if (pAsso->bValid
				&& (pAsso->indice==indice)
				&& (pAsso->type==type))
			break;
		}
	}
	else
	{
		SNDLST2_M_DynamicForEachElementOf(&association.pList,pAsso,i)
		{
			if (pAsso->bValid
				&& (pAsso->indice==indice)
				&& (pAsso->evt.pstPtr==evt)
				&& (pAsso->type==type))
			break;
		}
	}

	return pAsso;
}


/*
 *=============================================================================
 *	get_association_channel
 *
 *  Description : Get the first association found used by a channel/event couple
 *=============================================================================
 *  Input
 *			channel : sound channel id
 *			indice : sound object id
 *			type : sound object type id
 * 			evt : sound event played
 *
 *  Output
 *			asso : association pointer or NULL if not found
 *
 *=============================================================================
 *  Creation date :	01/06/99            Author :  Pascal Lalancette           
 *=============================================================================
 *  Modification date :				    Author : 
 *  Modifications : 
 *=============================================================================
 */
pASSOCIATION_DESCRIPTION get_association_channel(long channel, long indice,long type,void* evt)
{

	pASSOCIATION_DESCRIPTION pAsso;
	int i=0;

	if (evt==NULL)
	{
		SNDLST2_M_DynamicForEachElementOf(&association.pList,pAsso,i)
		{
			if (pAsso->bValid
				&& (pAsso->channel == channel)
				&& (pAsso->indice == indice)
				&& (pAsso->type == type))
			break;
		}
	}
	else
	{
		SNDLST2_M_DynamicForEachElementOf(&association.pList,pAsso,i)
		{
			if (pAsso->bValid
				&& (pAsso->channel == channel)
				&& (pAsso->indice == indice)
				&& (pAsso->evt.pstPtr == evt)
				&& (pAsso->type == type))
			break;
		}
	}

	return pAsso;
}


/*
 *=============================================================================
 *	stop_all_son_objet
 *
 *  Description : Stop any sounds assoicated with a object (except when flag
 *					Stopable is FALSE).Called by KillObjectSound or 
 *					SendRequetsSound to Stop event
 *=============================================================================
 *  Input
 *			indice : sound object id
 *			type : sound object type id
 *
 *  Output
 *			None
 *
 *=============================================================================
 *  Creation date :			            Author :            
 *=============================================================================
 *  Modification date : 01/06/99	    Author : Pascal Lalancette 
 *  Modifications : Changed to support get_association_object()
 *=============================================================================
 */
void stop_all_son_objet(long indice,long type)
{
   pASSOCIATION_DESCRIPTION pAsso;
 
    while ((pAsso=get_association_object(indice,type,NULL))!=NULL)
    {
        if (pAsso->evt.pstPtr->bStopable)
            SND_fn_vStopSnd(pAsso->voice);
         else
			invalidate_ptrvalid_snd(pAsso->voice);
        
		 erase_association(pAsso);
    }
}
 

/*
 *=============================================================================
 *	stop_un_son_objet
 *
 *  Description : Stop any instance of a specific event associated with a
 *					specific object (except is stopbale flag is FALSE).
 *					Called by KillObjectSound, or SendRequetsSound for Stop event
 *=============================================================================
 *  Input
 *			indice : sound object id
 *			type : sound object type id
 * 			evt : sound event played
 *
 *  Output
 *			None
 *
 *=============================================================================
 *  Creation date :			            Author :            
 *=============================================================================
 *  Modification date : 01/06/99	    Author : Pascal Lalancette 
 *  Modifications : Changed to support get_association_object()
 *=============================================================================
 */
void stop_un_son_objet(long indice,long type,SND_tduRefEvt evt)
{
	pASSOCIATION_DESCRIPTION pAsso;

	while ((pAsso=get_association_object(indice,type,evt.pstPtr))!=NULL)
	{
		if (pAsso->evt.pstPtr->bStopable)
			SND_fn_vStopSnd(pAsso->voice);
		else
			invalidate_ptrvalid_snd(pAsso->voice);
			erase_association(pAsso);
	}

}
 
 
/*-----------------------------------------------------------------
		Stop any sounds for a specific sound object type (whatever is Stopbale flag)
-----------------------------------------------------------------*/
void stop_son_type_all(long type)
{
	pASSOCIATION_DESCRIPTION pAsso,pAssoNext;
	int i=0;

	SNDLST2_M_DynamicForEachMovingElementOf(&association.pList,pAsso,pAssoNext,i)
	{
		if ((pAsso->bValid) && (pAsso->type==type))
		{
			SND_fn_vStopSnd(pAsso->voice);
			erase_association(pAsso);
		}
	}
}
 
/*-----------------------------------------------------------------
		Stop any sound for any objects whatever is stopable flag
-----------------------------------------------------------------*/
void stop_son_all(void)
{
	pASSOCIATION_DESCRIPTION pAsso,pAssoNext;
	int i=0;

	SNDLST2_M_DynamicForEachMovingElementOf(&association.pList,pAsso,pAssoNext,i)
	{
		if (pAsso->bValid)
			SND_fn_vStopSnd(pAsso->voice);
	
		erase_association(pAsso);
	}
}
 
/*-----------------------------------------------------------------
		Stop any sound except for a specific type
-----------------------------------------------------------------*/
void stop_son_type_but_all(long type)
{
	pASSOCIATION_DESCRIPTION pAsso,pAssoNext;
	int i=0;

	SNDLST2_M_DynamicForEachMovingElementOf(&association.pList,pAsso,pAssoNext,i)
	{
		if ((pAsso->bValid) && (pAsso->type!=type)) /* this is the line with the difference*/
		{
			SND_fn_vStopSnd(pAsso->voice);
			erase_association(pAsso);
		}
	}
}



 
void get_RollOff(long indice,long type,SoundParam* pstSoundParam)
{
    RollOffParam* pstRollOff;
 
    pstRollOff=&(SND_M_GetExtraParamFromSoundParam(pstSoundParam))->stRollOff;
    pstSoundParam->iFlags&=~C_SOUNDPARAM_ROLLOFF;
 
    /*raj du RollOff */
    if (g_d_pstTypeObjectSoundInfos[type].pfnRollOff)
    {/*si fonction de callback */
            if ((*g_d_pstTypeObjectSoundInfos[type].pfnRollOff)(indice,pstRollOff))
            {/*si focntion retourne TRUE*/
                    pstSoundParam->iFlags|=C_SOUNDPARAM_ROLLOFF;
            }
    }
}
 
void set_SwitchParam(long indice,long type,SoundParam* pstSoundParam)
{
        SwitchParam* pstSwitch;
 
        pstSwitch=&(SND_M_GetExtraParamFromSoundParam(pstSoundParam))->stSwitch;
 
        pstSoundParam->iFlags|=C_SOUNDPARAM_SWITCH;
        pstSwitch->lObjectType=type;
        pstSwitch->lObjectId=indice;
}
 
/*-----------------------------------------------------
     Check if microphone function are OK
-------------------------------------------------------*/
void check_micro_fct(void)
{
        snd_assert(g_st_pfnRetMicroSound.X!=NULL);
        snd_assert(g_st_pfnRetMicroSound.Y!=NULL);
        snd_assert(g_st_pfnRetMicroSound.Z!=NULL);
        snd_assert(g_st_pfnRetMicroSound.VX!=NULL);
        snd_assert(g_st_pfnRetMicroSound.VY!=NULL);
        snd_assert(g_st_pfnRetMicroSound.VZ!=NULL);
        snd_assert(g_st_pfnRetMicroSound.DTX!=NULL);
        snd_assert(g_st_pfnRetMicroSound.DTY!=NULL);
        snd_assert(g_st_pfnRetMicroSound.DTZ!=NULL);
        snd_assert(g_st_pfnRetMicroSound.DNX!=NULL);
        snd_assert(g_st_pfnRetMicroSound.DNY!=NULL);
        snd_assert(g_st_pfnRetMicroSound.DNZ!=NULL);
        snd_assert(g_st_pfnRetMicroSound.Filtre!=NULL);
}
 
 
/*
 *=============================================================================
 *	fn_bIsChannelActive,
 * 
 *  Description : Call the channel callback to see if its still active
 *=============================================================================
 *
 *=============================================================================
 *  Creation date : 02/06/99            Author : Pascal Lalancette            
 *=============================================================================
 *  Modification date :				    Author : 
 *  Modifications :
 *=============================================================================
 */
SndBool fn_bIsChannelActive(long channel, long indice, long type)
{
	return (g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.Active)(channel, indice);
}



/*
 *=============================================================================
 *	fn_vComputeRelToAbsCoord,
 * 
 *  Description : Convert a relative vector to an absolute world coordiante vector
 *
 *=============================================================================
 *
 *=============================================================================
 *  Creation date : 02/06/99            Author : Pascal Lalancette            
 *=============================================================================
 *  Modification date :				    Author : 
 *  Modifications :
 *=============================================================================
 */
SndVector fn_vComputeRelToAbsCoord(SndVector abs, SndVector rel, SndVector i, SndVector j, SndVector k )
{

	SndVector ret;

	//Do rotation to translate in world coordinate
	ret.x = SND_fn_rMulRealRealSnd(rel.x , i.x) + SND_fn_rMulRealRealSnd(rel.y , j. x) + SND_fn_rMulRealRealSnd(rel.z , k.x);
	ret.y = SND_fn_rMulRealRealSnd(rel.x , i.y) + SND_fn_rMulRealRealSnd(rel.y , j. y) + SND_fn_rMulRealRealSnd(rel.z , k.y);
	ret.z = SND_fn_rMulRealRealSnd(rel.x , i.z) + SND_fn_rMulRealRealSnd(rel.y , j. z) + SND_fn_rMulRealRealSnd(rel.z , k.z);

	ret.x += abs.x;
	ret.y += abs.y;
	ret.z += abs.z;

	return ret;

}



/*
 *=============================================================================
 *	fill_pre_filled_param
 *
 *  Description : Get geometrical parameters for a specific object. Called only
 *					once for each channel. pstPreFilledParam will be used many
 *					time for each event associated with this channel.
 *
 *=============================================================================
 *  Input
 *			channel : sound channel id
 *			indice : sound object id
 *			type : sound object type id
 *
 *  Output
 *			pstPreFilledParam : Will contain the geometrical parameters
									(X,Y,Z,VX,VY,VZ,REVERB)
 *
 *=============================================================================
 *  Creation date :			            Author :            
 *=============================================================================
 *  Modification date : 01/06/99	    Author : Pascal Lalancette 
 *  Modifications : Changed to support get_association_object()
 *=============================================================================
 */
void fill_pre_filled_param(long channel, long indice,long type,SoundParam* pstPreFilledParam)
{
	int                     i;
	pMICRO_DESCRIPTION      pMicro;

	SndVector I,J,K;
	SndVector ChannelPos, ObjectPos, ChannelVit, ObjectVit;
	SndVector AbsPos, AbsVit;

	pstPreFilledParam->iFlags=0;

	/*geometrical parameters*/
	if (channel == SND_C_CHANNEL_FANTOME)
	{

		if (indice!=SND_C_OBJET_FANTOME)
		{
			pstPreFilledParam->Pos.x=(g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.X)(indice);
			pstPreFilledParam->Pos.y=(g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.Y)(indice);
			pstPreFilledParam->Pos.z=(g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.Z)(indice);
			pstPreFilledParam->Vit.x=(g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.VX)(indice);
			pstPreFilledParam->Vit.y=(g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.VY)(indice);
			pstPreFilledParam->Vit.z=(g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.VZ)(indice);
			pstPreFilledParam->ucReverb=(g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.REVERB)(indice);
			pstPreFilledParam->ucPan=C_SOUNDPAN_MEDIAN;
			pstPreFilledParam->ucSpace=C_SOUNDSPACE_FRONT;

			if (!g_bDopplerActive)
				pstPreFilledParam->iFlags|=C_SOUNDPARAM_NO_DOPPLER;
		}
		else
		{
			//FANTOME object no dynamic location
			pstPreFilledParam->ucPan = C_SOUNDPAN_MEDIAN;
			pstPreFilledParam->ucReverb = NO_REVERB;
			pstPreFilledParam->ucSpace = C_SOUNDSPACE_FRONT;
			pstPreFilledParam->iFlags |= (C_SOUNDPARAM_NO_POSITION | C_SOUNDPARAM_NO_DOPPLER);
		}

	}
	else
	{
		if( g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.bAbsCoord )
		{
			//We are in absolute coordinate. Only use channel callback for position
			pstPreFilledParam->Pos.x=(g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.X)(channel, indice);
			pstPreFilledParam->Pos.y=(g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.Y)(channel, indice);
			pstPreFilledParam->Pos.z=(g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.Z)(channel, indice);
			pstPreFilledParam->Vit.x=(g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.VX)(channel, indice);
			pstPreFilledParam->Vit.y=(g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.VY)(channel, indice);
			pstPreFilledParam->Vit.z=(g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.VZ)(channel, indice);
			pstPreFilledParam->ucReverb=(g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.REVERB)(indice);
			pstPreFilledParam->ucPan=C_SOUNDPAN_MEDIAN;
			pstPreFilledParam->ucSpace=C_SOUNDSPACE_FRONT;
		}
		else
		{
			//We are in relative coordinate. We have to use the direction of
			//the world to compute the position of the channel.
			(g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.VectorI)(indice, &I);
			(g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.VectorJ)(indice, &J);
			(g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.VectorK)(indice, &K);
					
			ChannelPos.x = (g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.X)(channel, indice);
			ChannelPos.y = (g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.Y)(channel, indice);
			ChannelPos.z = (g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.Z)(channel, indice);

			ObjectPos.x = (g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.X)(indice);
			ObjectPos.y = (g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.Y)(indice);
			ObjectPos.z = (g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.Z)(indice);

			AbsPos = fn_vComputeRelToAbsCoord(ObjectPos, ChannelPos, I, J, K);

			ChannelVit.x = (g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.VX)(channel, indice);
			ChannelVit.y = (g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.VY)(channel, indice);
			ChannelVit.z = (g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.VZ)(channel, indice);

			ObjectVit.x = (g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.VX)(channel, indice);
			ObjectVit.y = (g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.VY)(channel, indice);
			ObjectVit.z = (g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.VZ)(channel, indice);

			AbsVit = fn_vComputeRelToAbsCoord(ObjectVit, ChannelVit, I, J, K);

			//Fill the param structure
			pstPreFilledParam->Pos.x = AbsPos.x;
			pstPreFilledParam->Pos.y = AbsPos.y;
			pstPreFilledParam->Pos.z = AbsPos.z;
			pstPreFilledParam->Vit.x = AbsVit.x;
			pstPreFilledParam->Vit.y = AbsVit.y;
			pstPreFilledParam->Vit.z = AbsVit.z;
			pstPreFilledParam->ucReverb=(g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.REVERB)(indice);
			pstPreFilledParam->ucPan=C_SOUNDPAN_MEDIAN;
			pstPreFilledParam->ucSpace=C_SOUNDSPACE_FRONT;

		}


	}		
		
	/*---link micro*/
	SNDLST2_M_DynamicForEachElementOf(&micros_sound.pList,pMicro,i)
	{
		snd_assert(i!=pstPreFilledParam->iNbLinks);
		
		if (indice!=SND_C_OBJET_FANTOME)
			pstPreFilledParam->astMicro[i].bLinked=(g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.MicroLink)(indice,(long)pMicro);
		else
			pstPreFilledParam->astMicro[i].bLinked=TRUE;
		
		pstPreFilledParam->astMicro[i].lId=pMicro->sndId;
	}

	/*RollOff parameter*/
	get_RollOff(indice,type,pstPreFilledParam);

	/*Switch informations (used by PlaySnd)*/
	set_SwitchParam(indice,type,pstPreFilledParam);

	#ifdef SUPERVISATER
	dbgSND_fn_vSetPosObject(indice,pstPreFilledParam);
	#endif

}
 
/*--------------------------------------------------------------
		Get dynamic parameters for a event/object
		Parameters: indice=sound object id
			type=sound object type id
			evt=sound event
			param(OUT)=SoundParam to compute (struct will be fiil by this function)
			deTune=random detuning paraeter
			pstPreFilledParam(IN)=store previous call to location callback
---------------------------------------------------------------*/
void get_param_objet2(long indice,long type,SND_tduRefEvt evt,SoundParam* param,SndReal deTune,SoundParam* pstPreFilledParam)
{
        SndReal                 extra_par;
        long                    extra_res;
		SndReal                 rCoefA,rCoefB;
		long					lVolumeType,lVolumeObject;
 
		/*copy of pre-filled geometrical soundparam (cf fill_pre_filled_param)*/
		SND_fn_vCopySoundParam(param,pstPreFilledParam);
 
		/*volume line*/
        if (g_d_pstTypeObjectSoundInfos[type].pstVolumeLine!=NULL)
        {
                param->ucVol=(unsigned char)g_d_pstTypeObjectSoundInfos[type].pstVolumeLine->lVol;
                param->iFlags|=C_SOUNDPARAM_COEF_VOL;
        }
		else
			param->ucVol=C_SOUNDVOL_MAXI;
 
        /*change-volume event*/
		lVolumeType=fn_lGetVolumeForType(type);
		lVolumeObject=fn_lGetVolumeForObject(indice,type);
		if ((lVolumeType!=C_SOUNDVOL_MAXI) || (lVolumeObject!=C_SOUNDVOL_MAXI))
		{
			param->ucVol=(unsigned char)((param->ucVol*lVolumeType*lVolumeObject)>>14);
			param->iFlags|=C_SOUNDPARAM_COEF_VOL;
		}
 
		/*one Detune for each Sound (not only for each object)*/
		param->Freq=deTune;
 
        /*---Extra Pitch*/
        if ((evt.pstPtr->eType==EVT_SON_PITCH) 
                || ((evt.pstPtr->eType==EVT_SON_EXTRA) && (evt.pstPtr->uParams.stExtraAll.rtCoefPitch)))
        {
            if (evt.pstPtr->eType==EVT_SON_PITCH)
            {
                    rCoefA=evt.pstPtr->uParams.stExtraParam.CoefA;
                    rCoefB=evt.pstPtr->uParams.stExtraParam.CoefB;
            }
            else
                    SND_fn_vSndRealTwinToSndReal(evt.pstPtr->uParams.stExtraAll.rtCoefPitch,&rCoefA,&rCoefB);
 
            (g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.ExtraCoef)(indice,evt,&extra_par,NULL,NULL);
			extra_par=SND_fn_rMulRealRealSnd(extra_par,rCoefA)+rCoefB;
			param->Freq=SND_fn_rMulRealRealSnd(extra_par,param->Freq);
 
			snd_assert(param->Freq>0);
        }
 
        /*---Extra Volume*/
        if ((evt.pstPtr->eType==EVT_SON_VOLUME) 
                || ((evt.pstPtr->eType==EVT_SON_EXTRA) && (evt.pstPtr->uParams.stExtraAll.rtCoefVol)))
        {
            if (evt.pstPtr->eType==EVT_SON_VOLUME)
            {
                    rCoefA=evt.pstPtr->uParams.stExtraParam.CoefA;
                    rCoefB=evt.pstPtr->uParams.stExtraParam.CoefB;
            }
            else
                    SND_fn_vSndRealTwinToSndReal(evt.pstPtr->uParams.stExtraAll.rtCoefVol,&rCoefA,&rCoefB);
 
            (g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.ExtraCoef)(indice,evt,NULL,NULL,&extra_par);
            extra_res=M_RealToIntSnd(SND_fn_rMulRealRealSnd(extra_par,rCoefA)+rCoefB);
            if (extra_res<0)
				param->ucVol=0;
            else
            {
                if (extra_res<=127)
                {
                    if (param->iFlags & C_SOUNDPARAM_COEF_VOL)
                        param->ucVol=(unsigned char)((extra_res*param->ucVol)>>7);
                    else
                        param->ucVol=(unsigned char)extra_res;
                }
                else
                {
                    if (!(param->iFlags & C_SOUNDPARAM_COEF_VOL))
                        param->ucVol=C_SOUNDVOL_MAXI;
                }
            }
            param->iFlags|=C_SOUNDPARAM_COEF_VOL;
        }
 
        /*---Extra Pan*/
        if ((evt.pstPtr->eType==EVT_SON_PAN) 
                || ((evt.pstPtr->eType==EVT_SON_EXTRA) && (evt.pstPtr->uParams.stExtraAll.rtCoefPan)))
        {
            if (evt.pstPtr->eType==EVT_SON_PAN)
            {
                    rCoefA=evt.pstPtr->uParams.stExtraParam.CoefA;
                    rCoefB=evt.pstPtr->uParams.stExtraParam.CoefB;
            }
            else
                    SND_fn_vSndRealTwinToSndReal(evt.pstPtr->uParams.stExtraAll.rtCoefPan,&rCoefA,&rCoefB);
 
            (g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound.ExtraCoef)(indice,evt,NULL,&extra_par,NULL);
            extra_res=M_RealToIntSnd(SND_fn_rMulRealRealSnd(extra_par,rCoefA)+rCoefB);
            if (extra_res<0) 
				param->ucPan=0;
            else
            {
                    if (extra_res>127) param->ucPan=127;
                    else param->ucPan=(unsigned char)extra_res;
            }
            param->iFlags|=C_SOUNDPARAM_NO_POSITION;
        }
}
 


/*
 *=============================================================================
 *	get_param_objet
 *
 *  Description : Get dynamic parameters for a event/channel.
 *
 *=============================================================================
 *  Input
 *			channel : sound channel id
 *			indice : sound object id
 *			type : sound object type id
 *			evt : event associated with the object
 *			deTune : deTune range
 *
 *  Output
 *			param : Will contain the dynaimc parameters
 *
 *=============================================================================
 *  Creation date :			            Author :            
 *=============================================================================
 *  Modification date : 01/06/99	    Author : Pascal Lalancette 
 *  Modifications : Changed to support channel
 *=============================================================================
 */
void get_param_objet(long channel, long indice,long type,SND_tduRefEvt evt,SoundParam* param,SndReal deTune)
{

	SoundParam *pstPreFilledParam;
#ifdef NB_MICRO_MAX
	SoundParam stSoundParam;
#endif


#ifdef NB_MICRO_MAX
	pstPreFilledParam=&stSoundParam;
	stSoundParam.iNbLinks=g_iNbActiveMicros;
#else
	pstPreFilledParam=SND_fn_pCreateSoundParam(g_iNbActiveMicros);
#endif

	//Fill Sound Param with channel specific info
	fill_pre_filled_param(channel, indice,type,pstPreFilledParam);
	//Fill Sound Param with object specific info
	get_param_objet2(indice,type,evt,param,deTune,pstPreFilledParam);


#ifndef NB_MICRO_MAX
	SND_fn_vDestroySoundParam(pstPreFilledParam);
#endif

}
 
 
/*----------------------------------------------------------------------*/
/*              Detuning parameter*/
/*----------------------------------------------------------------------*/
SndReal fn_rGetDeTune(SND_tduRefEvt evt)
{
        SndReal delta;
 
        switch (evt.pstPtr->eType)
        {
                case EVT_SON_PLAY:
                        delta=evt.pstPtr->uParams.stPlay.stDeTune.rDelta;
                        break;
                case EVT_SON_PITCH:
                case EVT_SON_VOLUME:
                case EVT_SON_PAN:
                        delta=evt.pstPtr->uParams.stExtraParam.stDeTune.rDelta;
                        break;
                default:
                        delta=NO_DETUNING;
                        break;
        }
 
        if (delta!=NO_DETUNING)
                return (C_SNDREAL_1+SND_fn_rGetRandomSnd(delta*2)-delta);
        else
                return C_SNDREAL_1;
}
 
/*-------------------------------------------------------*/
/*      default ret function*/
/*-------------------------------------------------------*/


/*
 *=============================================================================
 *	fn_rRetObjectSoundSndRealDefault
 *	fn_ucRetObjectSoundREVERBDefault
 *	fn_vRetObjectSoundExtraCoefDefault
 *	fn_bRetObjectSoundMicroLinkDefault
 *	fn_vRetObjectSoundVectorIDefault
 *	fn_vRetObjectSoundVectorJDefault
 *	fn_vRetObjectSoundVectorKDefault
 *
 *  Description : Default object's callback function
 *
 *=============================================================================
 *  Input
 *
 *  Output
 *
 *=============================================================================
 *  Creation date :			            Author :            
 *=============================================================================
 *  Modification date : 01/06/99	    Author : Pascal Lalancette 
 *  Modifications : Added fn_vRetObjectSoundVectorIDefault,
 *					fn_vRetObjectSoundVectorJDefault
 *					and fn_vRetObjectSoundVectorKDefault functions.
 *=============================================================================
 */
SndReal fn_rRetObjectSoundSndRealDefault(long indice)
{
        return C_SNDREAL_0;
}
 
unsigned char fn_ucRetObjectSoundREVERBDefault(long indice)
{
        return NO_REVERB;
}
 
void fn_vRetObjectSoundExtraCoefDefault(long indice,SND_tduRefEvt evt,SndReal* pitch,SndReal* pan,SndReal* vol)
{
        if (pitch!=NULL)
                *pitch=C_SNDREAL_1;
        if (pan!=NULL)
                *pan=C_SNDREAL_1;
        if (vol!=NULL)
                *vol=C_SNDREAL_1;
        return;
}
 
long fn_lRetObjectSoundSwitchDefault(long indice,long type_switch)
{
        return 0;
}
 
SndBool fn_bRetObjectSoundMicroLinkDefault(long indice,long micro)
{
        return TRUE;
}
 
void fn_vRetObjectSoundVectorIDefault(long indice, SndVector* vect)
{
	if (vect!=NULL)
	{
		vect->x = C_SNDREAL_1;
		vect->y = C_SNDREAL_0;
		vect->z = C_SNDREAL_0;
	}
	return;
}

void fn_vRetObjectSoundVectorJDefault(long indice, SndVector* vect)
{
	if (vect!=NULL)
	{
		vect->x = C_SNDREAL_0;
		vect->y = C_SNDREAL_1;
		vect->z = C_SNDREAL_0;
	}

	return;
}

void fn_vRetObjectSoundVectorKDefault(long indice, SndVector* vect)
{
	if (vect!=NULL)
	{
		vect->x = C_SNDREAL_0;
		vect->y = C_SNDREAL_0;
		vect->z = C_SNDREAL_1;
	}

	return;

}

/*-------------------------------------------------------*/
/*      default RetMicroSound functions*/
/*-------------------------------------------------------*/
SndReal fn_rRetMicroSoundSndReal0Default(long indice)
{
        return 0;
}
 
SndReal fn_rRetMicroSoundSndReal1Default(long indice)
{
        return 0x10000;
}
 
long fn_lRetMicroSoundFILTREDefault(long indice)
{
        return 0;
}
 

/*
 *=============================================================================
 *	fn_rRetMicroSoundSndReal0Default,
 *	fn_rRetMicroSoundSndReal1Default,
 *	fn_bRetChannelSoundAbsCoordDefault
 * 
 *  Description : Default RetChannelSound functions
 *=============================================================================
 *
 *=============================================================================
 *  Creation date : 31/05/99            Author : Pascal Lalancette            
 *=============================================================================
 *  Modification date :				    Author : 
 *  Modifications :
 *=============================================================================
 */
SndReal fn_rRetChannelSoundSndReal0Default(long indice, long channel)
{
        return 0;
}
 
SndReal fn_rRetChannelSoundSndReal1Default(long indice, long channel)
{
        return 0x10000;
}

SndBool fn_bRetChannelSoundActiveDefault(long indice, long channel)
{
	return TRUE;
}
 
SndBool fn_bRetChannelSoundAbsCoordDefault(long indice, long channel)
{
	return TRUE;
}

 
/*-------------------------------------------------------
	Init of g_st_pfnRetMicroSound
------------------------------------------------------*/
void init_micro_fct(void)
{
        SNDLST2_M_DynamicInitAnchor(&micros_sound.pList);
        g_iNbActiveMicros=0;
 
        g_st_pfnRetMicroSound.X=fn_rRetMicroSoundSndReal0Default;
        g_st_pfnRetMicroSound.Y=fn_rRetMicroSoundSndReal0Default;
        g_st_pfnRetMicroSound.Z=fn_rRetMicroSoundSndReal0Default;
        g_st_pfnRetMicroSound.VX=fn_rRetMicroSoundSndReal0Default;
        g_st_pfnRetMicroSound.VY=fn_rRetMicroSoundSndReal0Default;
        g_st_pfnRetMicroSound.VZ=fn_rRetMicroSoundSndReal0Default;
        g_st_pfnRetMicroSound.DTX=fn_rRetMicroSoundSndReal1Default;
        g_st_pfnRetMicroSound.DTY=fn_rRetMicroSoundSndReal0Default;
        g_st_pfnRetMicroSound.DTZ=fn_rRetMicroSoundSndReal0Default;
        g_st_pfnRetMicroSound.DNX=fn_rRetMicroSoundSndReal0Default;
        g_st_pfnRetMicroSound.DNY=fn_rRetMicroSoundSndReal0Default;
        g_st_pfnRetMicroSound.DNZ=fn_rRetMicroSoundSndReal1Default;
        g_st_pfnRetMicroSound.Filtre=fn_lRetMicroSoundFILTREDefault;
}
 
/*-------------------------------------------------------
		
        Init la table de type d'objet pour RetObjectSound..
------------------------------------------------------*/
void init_object_type(void)
{
        nb_object_type=0;
        SND_fn_lAddObjectTypeSound(&g_astTypeObjectSoundInfosDefault);
}
 
/*-------------------------------------------------------
        desInit la table de type d'objet 
------------------------------------------------------*/
void desinit_object_type(void)
{
        SND_fn_vFreeSndEx(E_ucSndBlockMain,g_d_pstTypeObjectSoundInfos);
}
 
/*-------------------------------------------------------
        desInit la table de lignes de volumes
------------------------------------------------------*/
void desinit_volume_lines(void)
{
        ptdstVolumeLine pLine,pLineNext;
        int i;
 
        SNDLST2_M_DynamicForEachMovingElementOf(&(g_VolumeLines.pList),pLine,pLineNext,i)
        {
                SND_fn_vFreeSndEx(E_ucSndBlockMain,pLine);
 
                                #ifdef SUPERVISATER
                                dbgSND_fn_vKillVolumeLine((long)pLine);
                                #endif
        }
 
        nb_volume_lines=0;
}
 
#ifdef DEBUG_SON
/*-----------------------------------------------------
        genere une liste des association
-------------------------------------------------------*/
void liste_of_association(char *texte,long size)
{
        char temp[256];
        int i;
        pASSOCIATION_DESCRIPTION pAsso;
 
        texte[0]='\0';
 
        SNDLST2_M_DynamicForEachElementOf(&association.pList,pAsso,i)
        {
                sprintf(temp,"V:%8x-O:%8x-Evt:%8x(Id %d)%s\xd\xa",pAsso->voice,pAsso->indice,pAsso->evt,pAsso->evt.pstPtr->Id
                                        ,((pAsso->res_hi.pstPtr->eType==TYPE_SWITCH)?" SWITCH":""));
                strncat(texte,temp,size-strlen(texte)-1);
 
				/*
                sprintf(temp,"(V:%8x-O:%8x-Evt:%8x(Id %d)",pAsso->voice,pAsso->indice,pAsso->evt,pAsso->evt.pstPtr->Id);
                                switch (pAsso->res_hi.pstPtr->eType)
                                {
                                case TYPE_SWITCH:
                                        strncat(temp," SWITCH)\n",size-strlen(temp)-1);break;
                                default:
                                        strncat(temp," )\n",size-strlen(temp)-1);break;
                                }
								*/
        }
 
        if (texte[0]=='\0')
                sprintf(texte,"Aucune association");
}
#endif /*Debug*/
 
 
void init_association()
{
        SNDLST2_M_DynamicInitAnchor(&association.pList);
}

/*-----------------------------------------------------
     Check if channel function are OK
-------------------------------------------------------*/
void check_channel_fct(long type)
{
        snd_assert(g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.X!=NULL);
        snd_assert(g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.Y!=NULL);
        snd_assert(g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.Z!=NULL);
        snd_assert(g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.VX!=NULL);
        snd_assert(g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.VY!=NULL);
        snd_assert(g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.VZ!=NULL);
        snd_assert(g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound.Active!=NULL);

}

#endif /*NO_ACP_SOUND*/
 


/****************************************************************************************/
/****************************************************************************************/
/*																						*/
/*							Fonctions publiques											*/
/*																						*/
/*																						*/
/****************************************************************************************/
/****************************************************************************************/

/*
 *=============================================================================
 *	SND_fn_iInitSound
 *
 *  Description : Initialize SOUND3D librairy
 *
 *=============================================================================
 *
 *  Input
 *			pInitStruct : structure containing init information
 *
 *
 *  Output
 *			C_INITSOUND_OK if success,
 *			C_INITSOUND_FAILED if failed						
 *			C_INITRUNNING if processing.
 *
 *=============================================================================
 *  Creation date :			            Author :            
 *=============================================================================
 *  Modification date :				    Author : 
 *  Modifications : 
 *=============================================================================
 */
int SND_fn_iInitSound(SND_tdstInitStruct *pInitStruct)
{
#ifndef NO_ACP_SOUND

	int iRet;

	/*init acp*/
	SND_fn_vInitThreadSnd();
	SND_fn_vInitErrorSnd(pInitStruct);
	SND_fn_vInitMallocSnd();

	SND_fn_vInitOptions(pInitStruct);

#ifndef DREAMCAST
	/*init de variables internes*/
	init_object_type();
#endif /*DREAMCAST*/

	init_micro_fct();

	init_association();

	/*init de la couche hard*/
	iRet=SND_fn_iInitSnd(pInitStruct);

	/* Version specific inits:*/


#ifndef NO_ACP_LDBIN
	SND_fn_vInitBankSnd(NULL);
#endif

	SND_fn_vQuitCriticalSectionThreadSnd();

#ifdef SUPERVISATER
	SND_fn_vLaunchSupervisater(pInitStruct);
#endif

	g_bInitDoneSound=TRUE;

	return iRet;
#else
	return C_INIT_FAILED;
#endif /*NO_ACP_SOUND*/
}
 
  
 
/*------------------------------------------------------------*/
/*      TestInitSound:test de la fin de l'initialisation de SOUND3D*/
/*      Entree:neant*/
/*      Sortie:C_INITSOUND_OK si reussite,C_INITSOUND_FAILED sinon*/
/*              C_INIT_RUNNING si en cours*/
/*------------------------------------------------------------*/
int SND_fn_iTestInitSound(void)
{
#ifndef NO_ACP_SOUND
        /*version non asynchrone*/
    return C_INITSOUND_OK;
#else
        return C_INIT_FAILED;
#endif /*NO_ACP_SOUND*/
}
 
/*------------------------------------------------------------*/
/*      InitSound:desinitialisation dela librairie SOUND3D*/
/*      Entree:neant*/
/*      Sortie:neant*/
/*------------------------------------------------------------*/
void SND_fn_vDesInitSound(void)
{
#ifndef NO_ACP_SOUND
#ifdef SUPERVISATER
        SND_fn_vKillSupervisater();
#endif
 
    if (g_bInitDoneSound)
    {
        g_bInitDoneSound=FALSE;
 
		/*desinit de haut-niveau*/
		SND_fn_vDestroyAllMicroSound();

		SND_fn_vEnterCriticalSectionThreadSnd();

		stop_son_all();

		/*deinit de variables internes*/
		desinit_object_type();
		desinit_volume_lines();
 
		/* Version specific desinits:*/
 
#ifdef SND_SCRIPT_VERSION
        SND_fn_vDesInitScriptSnd();
#endif /*SND_SCRIPT_VERSION*/
 
#ifdef SND_HYBRID_VERSION
		SND_fn_bDesInitDataLoadSnd();
#endif /*SND_HYBRID_VERSION*/
 
#ifndef NO_ACP_LDBIN
		SND_fn_vDesInitBankSnd();
#endif /*NO_ACP_LDBIN*/
 
		/*desinit de la couche hard*/
		SND_fn_vDesInitSnd();

		/*desinit acp*/
		SND_fn_vDesInitThreadSnd();
		SND_fn_vDesInitMallocSnd();
		SND_fn_vDesInitErrorSnd();

		SND_fn_vDesInitOptions();
    }
#endif /*NO_ACP_SOUND*/
}
 
/*------------------------------------------------------------*/
/*      SetDopplerFactorSound: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_fn_vSetDopplerFactorSound(SndReal factor)
{
#ifndef NO_ACP_SOUND
        if (factor==SND_C_NO_DOPPLER)
        {
                g_bDopplerActive=FALSE;
        }
        else
        {
                snd_assert(factor>0);
 
                g_bDopplerActive=TRUE;
        }
 
        SND_fn_vSetDopplerFactorSnd(factor);
#endif
}
 
/*------------------------------------------------------------*/
/*      SND_fn_vSetDefaultRollOffSound:change default RollOff value*/
/*      Parameter:new RollOff values*/
/*      Sortie:neant*/
/*------------------------------------------------------------*/
void SND_fn_vSetDefaultRollOffSound(RollOffParam *rolloff)
{
#ifndef NO_ACP_SOUND
        SND_fn_vSetDefaultRollOffSnd(rolloff);
#endif
}
 
#ifndef NO_ACP_SOUND
/*
 *=============================================================================
 *	fn_vRajAllVolumeForLine
 *
 *  Description : Update all volumes of a volume line (non-dyanimc included).
 *					Very similar to SND_SynchroSound but add non-dynamic
 *					volume line.
 *
 *	Note : This function does'nt process Switch
 *
 *=============================================================================
 *  Input:	pVolumeLine : Volume lime
 *
 *  Output : None
 *
 *=============================================================================
 *  Creation date :			            Author :            
 *=============================================================================
 *  Modification date : 01/06/99	    Author : Pascal Lalancette 
 *  Modifications : Add Sound channel support
 *=============================================================================
 */
void fn_vRajAllVolumeForLine(ptdstVolumeLine pVolumeLine)
{
	int i;
	SoundParam *pstSoundParam;
	pASSOCIATION_DESCRIPTION pAsso,pAssoNext;

#ifdef NB_MICRO_MAX
	SoundParam stSoundParam;
#endif

	SND_fn_vEnterCriticalSectionThreadSnd();

#ifdef NB_MICRO_MAX
	pstSoundParam=&stSoundParam;
	stSoundParam.iNbLinks=g_iNbActiveMicros;
#else
	pstSoundParam=SND_fn_pCreateSoundParam(g_iNbActiveMicros);
#endif

	/*raj des objets*/
	SNDLST2_M_DynamicForEachMovingElementOf(&association.pList,pAsso,pAssoNext,i)
	{/*pour chaque association*/

		if (pAsso->bValid)
		{/*pour chaque association valide*/
			if (g_d_pstTypeObjectSoundInfos[pAsso->type].pstVolumeLine==pVolumeLine)
			{/*asso liee à la ligne -> raj*/
				get_param_objet(pAsso->channel, pAsso->indice,pAsso->type,pAsso->evt,pstSoundParam,pAsso->rDeTune);

				/*ressources Switch ou pas, meme traitement*/
				/*Switch, TestIsPlaying et autres seront appeles par SynchtoSound qui est là pour ça*/
				if (!SND_fn_bSetParamSnd(pAsso->voice,pstSoundParam))
				{/*son fini*/
					erase_association(pAsso);
				}
			}
	
			/*on ne touche pas aux autres sons (ça sert à rien)*/
		}
		else
		{/*voie desactivee*/
			erase_association(pAsso);
		}
	}

#ifndef NB_MICRO_MAX
	SND_fn_vDestroySoundParam(pstSoundParam);
#endif

	SND_fn_vQuitCriticalSectionThreadSnd();
}
#endif /*no_acp_sound*/
 
 
/*
 *=============================================================================
 *	SND_fn_vSynchroSound
 *
 *  Description : Update all parameters of all channels and objects
 *
 *
 *=============================================================================
 *  Input:	None
 *
 *  Output : None
 *
 *=============================================================================
 *  Creation date :			            Author :            
 *=============================================================================
 *  Modification date : 01/06/99	    Author : Pascal Lalancette 
 *  Modifications : Add Sound Channel support
 *=============================================================================
 */
void SND_fn_vSynchroSound(void)
{
#ifndef NO_ACP_SOUND
	int i;
	MicroParam micpar;
	SoundParam *pstSoundParam, *pstPreFilledParam = NULL;
	pASSOCIATION_DESCRIPTION pAsso,pAssoNext;
	pMICRO_DESCRIPTION pMicro;
	long prev_channel = -1, prev_indice = -1, prev_type = -1;

#ifdef NB_MICRO_MAX
	SoundParam stSoundParam,stPreFilledParam;
#endif

	SND_fn_vEnterCriticalSectionThreadSnd();

	//
	//Update micros
	//
    SNDLST2_M_DynamicForEachElementOf(&micros_sound.pList,pMicro,i)
    {
		GetMicroParam((long)pMicro,&micpar);

		SND_fn_vSetMicroParamSnd(pMicro->sndId,&micpar);

#ifdef SUPERVISATER
		dbgSND_fn_vSetPosMicro((long)pMicro,&micpar);
#endif
    }
    
	snd_assert(g_iNbActiveMicros==i);
 

#ifdef NB_MICRO_MAX
	pstSoundParam=&stSoundParam;
	stSoundParam.iNbLinks=g_iNbActiveMicros;
#else
    pstSoundParam=SND_fn_pCreateSoundParam(g_iNbActiveMicros);
#endif
 
	//
	//Update objects
	//
	SNDLST2_M_DynamicForEachMovingElementOf(&association.pList,pAsso,pAssoNext,i)
	{/*pour chaque asso*/
	
		if (pAsso->bValid)
		{/*pour chaque asso valide*/
			if ( (pAsso->evt.pstPtr->bDynamic) && pAsso->bDynamic)
				//Is the channel still active?  
				pAsso->bDynamic = fn_bIsChannelActive(pAsso->channel, pAsso->indice, pAsso->type);
        
			/*raj des params dynamiques*/
			if (pAsso->bDynamic)
			{
				if (!pstPreFilledParam)
				{/*first fill for pstPreFilledParam*/
				
#ifdef NB_MICRO_MAX
					pstPreFilledParam=&stPreFilledParam;
					stPreFilledParam.iNbLinks=g_iNbActiveMicros;
#else
					pstPreFilledParam=SND_fn_pCreateSoundParam(g_iNbActiveMicros);
#endif
					prev_channel = pAsso->channel;
					prev_indice = pAsso->indice;
					prev_type = pAsso->type;
					fill_pre_filled_param(prev_channel, prev_indice, prev_type, pstPreFilledParam);
				}
				else
				{
					if (pAsso->channel != prev_channel || pAsso->indice != prev_indice || pAsso->type != prev_type)
					{/*new object ->refill pstPreFilledParam*/
						
						prev_channel = pAsso->channel;
						prev_indice=pAsso->indice;
						prev_type=pAsso->type;
						fill_pre_filled_param(prev_channel, prev_indice, prev_type, pstPreFilledParam);
					}
					/*else */
					/*object's parameters have yet been computed*/
				}

				get_param_objet2(pAsso->indice,pAsso->type,pAsso->evt,pstSoundParam,pAsso->rDeTune,pstPreFilledParam);

				if (!SND_fn_bSetParamSnd(pAsso->voice,pstSoundParam))
				{/*son fini*/
					erase_association(pAsso);
				}
			}

		
			else/*evt à ne pas remettre à jour dynamiquement*/
				//Event or channel who doesnt need to be updated dynamicaly
				if (!SND_fn_bTestIsPlayingSnd(pAsso->voice))
					erase_association(pAsso);
		}
		else
		{/*voie desactivee*/
				erase_association(pAsso);
		}
	}
 
#ifndef NB_MICRO_MAX
		if (pstPreFilledParam)
			SND_fn_vDestroySoundParam(pstPreFilledParam);
 
        SND_fn_vDestroySoundParam(pstSoundParam);
#endif
 
		SND_fn_vSynchroSnd();
 
        SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}
 

/*
 *=============================================================================
 *	SND_fn_lSendRequestSound
 *
 *  Description : Process an event. 
 *
 *	Note: This function is still available for compatibility purpose.
 *	Use SND_fn_lSendRequestCannelSound instead.
 *
 *=============================================================================
 *  Input:	
 *			indice : object id
 *			evt :	event to interpret
 *			prio : priority level of this event
 *			proc: Callback call when the event has finished
 *
 *
 *  Output : Event handle
 *
 *=============================================================================
 *  Creation date :			            Author :            
 *=============================================================================
 *  Modification date : 01/06/99	    Author : Pascal Lalancette 
 *  Modifications : Add Sound Channel support
 *=============================================================================
 */
long SND_fn_lSendRequestSound(long indice,long type,SND_tduRefEvt evt,long prio,SND_td_pfn_vSoundCallback proc)
{
	return SND_fn_lSendRequestChannelSound(SND_C_CHANNEL_FANTOME, indice,type, evt,prio,proc);

}

/*
 *=============================================================================
 *	SND_fn_lSendRequestChannelSound
 * 
 *  Description : Event processing
 *=============================================================================
 *  Input  : indice : Object associated with the event (SND_C_OBJECT_FANTOME or user defined)
 *			 type : Object type (returned by SND_fn_lAddObectTypeSound2)
 *			 channel : Channel associated to the object
 *			 evt : References to the event to be interpreted
 *			 prio : Priority level 
 *			 proc : Callback function to be call when the sound is finished
 *
 *  Output : - Id of the event instance
 *			 - SND_C_EVT_FAILED if failure
 *			 - callback function parameter if callback succesfull
 *			 - SND_C_EVT_CALLBACK_FAILED
 *
 *=============================================================================
 *  Creation date : 20/05/99            Author : Pascal Lalancette            
 *=============================================================================
 *  Modification date :				    Author : 
 *  Modifications :
 *=============================================================================
 */
long SND_fn_lSendRequestChannelSound(long channel, long indice, long type, SND_tduRefEvt evt, long prio, SND_td_pfn_vSoundCallback proc)
{

#ifndef NO_ACP_SOUND
	SoundParam      *pstSoundParam;
#ifdef NB_MICRO_MAX
	SoundParam		stSoundParam;
#endif
	tduRefRes       res_hi;
#ifdef SUPERVISATER
	tduRefRes       res_low;
#endif
	long            voice;
	SndBool         use_callback;
	SndBool         evt_ok;
	long            lHandle;
	SndReal         rDeTune;
	pASSOCIATION_DESCRIPTION asso=NULL;

	res_hi.pstPtr=NULL;
	if (evt.pstPtr==EVT_FANTOME_PTR)
		return SND_C_EVT_FAILED;

	SND_fn_vEnterCriticalSectionThreadSnd();
 
#ifdef NB_MICRO_MAX
	pstSoundParam=&stSoundParam;
	stSoundParam.iNbLinks=g_iNbActiveMicros;
#else
    pstSoundParam=SND_fn_pCreateSoundParam(g_iNbActiveMicros);
#endif
        
    lHandle=HandleCallback++;
    if ((HandleCallback == SND_C_EVT_CALLBACK_FAILED) || (HandleCallback == SND_C_EVT_FAILED))
		HandleCallback=1;

    voice=-1;
    use_callback = FALSE;
    evt_ok = TRUE;

    switch (evt.pstPtr->eType)
    {
	case EVT_SON_PLAY:
    case EVT_SON_PITCH:
    case EVT_SON_VOLUME:
    case EVT_SON_PAN:
    case EVT_SON_EXTRA:
		if (!(asso = pre_associe_sound()))
        {
			evt_ok=FALSE;
			break;
        }
        if (evt.pstPtr->eType==EVT_SON_PLAY)
			res_hi.pstPtr=evt.pstPtr->uParams.stPlay.uResource.pstPtr;
        else if (evt.pstPtr->eType==EVT_SON_EXTRA)
	        res_hi.pstPtr=evt.pstPtr->uParams.stExtraAll.uResource.pstPtr;
        else
			res_hi.pstPtr=evt.pstPtr->uParams.stExtraParam.uResource.pstPtr;

        if (res_hi.pstPtr!=SND_C_RES_FANTOME_PTR)
        {
			/*tirage du parametre de DeTuning*/
			rDeTune=fn_rGetDeTune(evt);
			
			/*calcul des parametres */
			get_param_objet(channel, indice,type,evt,pstSoundParam,rDeTune);

			if ((voice = SND_fn_lPlaySnd(res_hi,pstSoundParam,prio,proc,lHandle,&(asso->bValid)))!=C_PLAY_FAILED)
			{/*son envoye*/

				associe_sound(asso, channel, indice, type, prio, voice, evt, res_hi, rDeTune, lHandle);
				if (proc)
					use_callback=TRUE;
			}
			else
			{
				erase_association(asso);
				evt_ok=FALSE;
			}
        }
        else
        {
			erase_association(asso);
			evt_ok=FALSE;
        }
        break;

    case EVT_SON_STOP:
        /*traitement d'un evt StopSon (arret d'1 son d'un objet)*/
        stop_un_son_objet(indice,type,evt.pstPtr->uParams.stStop.uEvt);
        break;

    case EVT_SON_STOP_ALL:
        /*traitement d'un evenemnt StopSonALL (arret de tous les ons d'un objet)*/
        stop_all_son_objet(indice,type);
        break;

    case EVT_SON_STOP_N_GO:
		/*traitement d'un evt. Stop'n'Go (arret d'un son, lancement d'un autre)*/
		stop_un_son_objet(indice,type,evt.pstPtr->uParams.stStopNGo.uEvtStop);
		if ((lHandle=SND_fn_lSendRequestChannelSound(channel, indice,type,evt.pstPtr->uParams.stStopNGo.uEvtGo,prio,proc))==SND_C_EVT_FAILED)
			evt_ok=FALSE;
		use_callback=TRUE;
		break;

    case EVT_SON_EFFET:
        /*evt de type SetEffect*/
        SND_fn_vSetEffectSnd(evt.pstPtr->uParams.stEffect.iIdEffect);
        break;
    
	case EVT_SON_CHANGE_VOLUME:
		if (evt.pstPtr->uParams.stChangeVolume.bConcernWithObjectType)
		{
			fn_vChangeVolumeForType(type,evt.pstPtr->uParams.stChangeVolume.lNewVolume);                                            

			SND_fn_vSynchroSound();
		}
		else
		{
			fn_vChangeVolumeForObject(indice,type,evt.pstPtr->uParams.stChangeVolume.lNewVolume);                                           
			
			SND_fn_vSynchroSound();
		}
		break;

    default:
        SND_M_DisplayError(E_uwSndInvalidTypeOfEvent,"");
        evt_ok=FALSE;
        break;
    }

#ifdef SUPERVISATER
	if (res_hi.pstPtr!=NULL)
		res_low=SND_fn_tduGetLowestResourceSnd(res_hi,pstSoundParam,FALSE);
	else
		res_low.pstPtr=NULL;
	
	dbgSND_fn_vAddHistoric(evt,indice,type,(long)asso,res_low.pstPtr);
#endif

#ifndef NB_MICRO_MAX
    SND_fn_vDestroySoundParam(pstSoundParam);
#endif
 
    /*---*/
    fnSetLastEventForSoundObjectType(type,evt.pstPtr);

    SND_fn_vQuitCriticalSectionThreadSnd();

    if (!evt_ok)
	    return SND_C_EVT_FAILED;
    if (proc && !use_callback)
		return SND_C_EVT_CALLBACK_FAILED;
    else
		return lHandle;

#else
    return SND_C_EVT_FAILED;

#endif /*NO_ACP_SOUND*/
}


/*------------------------------------------------------*/
/*      SetEffectSnd: installer un effet sonore*/
/*      Entree:id=designation de l'effet*/
/*      Sortie:neant*/
/*-------------------------------------------------------*/
void SND_fn_vSetEffectSound(long id_effect)
{
#ifndef NO_ACP_SOUND
        SND_fn_vSetEffectSnd(id_effect);
#endif
}
 
/*------------------------------------------------------------*/
/*      GetPos:obtenir la position theorique courante de la ressource*/
/*                      but principal=lip synchro*/
/*      Entree:handle=handle sur le son (code retourne par SendRequest)*/
/*      Sortie:position theorique en s (diferent du temps abslou ecoule)*/
/*------------------------------------------------------------*/
SndReal SND_fn_rGetPosSound(long handle)
{
#ifndef NO_ACP_SOUND
        pASSOCIATION_DESCRIPTION pAsso;
        SndBool bFound=FALSE;
        int i;
                SndReal ret;
 
        SND_fn_vEnterCriticalSectionThreadSnd();
 
        SNDLST2_M_DynamicForEachElementOf(&association.pList,pAsso,i)
        {
                if (pAsso->lHandle==handle)
                {
                        bFound=TRUE;
                        break;
                }
        }
 
        if (bFound)
        {
                ret=SND_fn_rGetPosSnd(pAsso->voice);
        }
        else
                ret=SND_C_POS_ENDED;
 
        SND_fn_vQuitCriticalSectionThreadSnd();
 
                return ret;
#else
        return SND_C_POS_UNKNOWN;
#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_fn_rGetLengthSound(long handle)
{
#ifndef NO_ACP_SOUND
        pASSOCIATION_DESCRIPTION pAsso;
        SndBool bFound=FALSE;
        int i;
 
        SNDLST2_M_DynamicForEachElementOf(&association.pList,pAsso,i)
        {
                if (pAsso->lHandle==handle)
                {
                        bFound=TRUE;
                        break;
                }
        }
 
        if (bFound)
        {
                return SND_fn_rGetLengthSnd(pAsso->voice);
        }
        else
#endif
                return SND_C_LENGTH_UNKNOWN;
}
 
 

/*
 *=============================================================================
 *	SND_fn_vKillChannelSound
 *
 *  Description : destruction of a channel
 *=============================================================================
 *  Input  : indice : Object associated
 *			 channel : Channel to kill
 *
 *  Output : None
 *
 *=============================================================================
 *  Creation date : 20/05/99            Author : Pascal Lalancette            
 *=============================================================================
 *  Modification date :				    Author : 
 *  Modifications :
 *=============================================================================
 */
void SND_fn_vKillChannelSound(long channel, long indice, long type)
{
#ifndef NO_ACP_SOUND
		 pASSOCIATION_DESCRIPTION pAsso;
	
		SND_fn_vEnterCriticalSectionThreadSnd();
				
		if (channel != SND_C_CHANNEL_FANTOME)
		{
		
			//Get Asso
			 pAsso = get_association_channel(channel, indice, type, NULL);
			
			//Stop the channel Update. The channel position will be freeze
			//(the SndParam struct wont be updated anymore)
			pAsso->bDynamic = FALSE;

		}
 
        SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}

/*
 *=============================================================================
 *	SetRetChannelSound
 *
 *  Description : Initialize channel callback function
 *=============================================================================
 *  Input  : ptrfct Pointer on callback funcion structure
 *
 *  Output : None
 *
 *=============================================================================
 *  Creation date : 20/05/99            Author : Pascal Lalancette            
 *=============================================================================
 *  Modification date :				    Author : 
 *  Modifications :
 *=============================================================================
 */
void SND_fn_vSetRetChannelTypeSound(long type, tdstAllRetChannelSound *ptrfct)
{
#ifndef NO_ACP_SOUND
	SND_fn_vEnterCriticalSectionThreadSnd();
 
	//Copy pointer strutucure
	 memcpy(&g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound,ptrfct,sizeof(tdstAllRetChannelSound));

	check_channel_fct(type);
 
    SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}



/*------------------------------------------------------------*/
/*      KillObjectSound:destruction d'un objet*/
/*      Entree:indice)objet detruit*/
/*      Sortie:neant*/
/*------------------------------------------------------------*/
void SND_fn_vKillObjectSound2(long indice,long type)
{
#ifndef NO_ACP_SOUND
        SND_fn_vEnterCriticalSectionThreadSnd();
 
        stop_all_son_objet(indice,type);
 
		fn_vResetVolumeForObject(indice,type);
		//fn_vChangeVolumeForObject(indice,type,C_SOUNDVOL_MAXI);
 
        SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}




void SND_fn_vKillObjectSound(long indice)
{
#ifndef NO_ACP_SOUND
      //  long type;

        /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
        /*obsolete function: please call SND_fn_vKillObjectSound2*/
        snd_assert(FALSE);
        /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
 
        SND_fn_vEnterCriticalSectionThreadSnd();
 
/*        stop_all_son_objet_old(indice);

        for (type=0;type<nb_object_type;type++)
			fn_vResetVolumeForObject(indice,type);
            //fn_vChangeVolumeForObject(indice,type,C_SOUNDVOL_MAXI);
 */
        SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}
 


/*------------------------------------------------------------*/
/*      KillAllObjectTypeSound:destruction de tous les objets d'un type donne*/
/*      Entree:type=type des objets à tuer*/
/*      Sortie:neant*/
/*------------------------------------------------------------*/
void SND_fn_vKillAllObjectTypeSound(long type)
{
#ifndef NO_ACP_SOUND
        SND_fn_vEnterCriticalSectionThreadSnd();
	
        stop_son_type_all(type);
 
		fn_vChangeVolumeForType(type,C_SOUNDVOL_MAXI);
 
        SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}
 
/*------------------------------------------------------------*/
/*      KillAllObjectSound:destruction de tous les objets*/
/*      Entree:neant*/
/*      Sortie:neant*/
/*------------------------------------------------------------*/
void SND_fn_vKillAllObjectSound(void)
{
#ifndef NO_ACP_SOUND
                long type;
 
        SND_fn_vEnterCriticalSectionThreadSnd();
 
        stop_son_all();
 
        for (type=0;type<nb_object_type;type++)
                fn_vChangeVolumeForType(type,C_SOUNDVOL_MAXI);
 
        SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}
 
/*------------------------------------------------------------*/
/*      KillAllObjectButTypeSound:destruction de tous les objets sauf d'un type donne*/
/*      Entree:type=type des objets à ne pas tuer*/
/*      Sortie:neant*/
/*------------------------------------------------------------*/
void SND_fn_vKillAllObjectButTypeSound(long type)
{
#ifndef NO_ACP_SOUND
        SND_fn_vEnterCriticalSectionThreadSnd();
 
        stop_son_type_but_all(type);
 
        SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}
 
/*------------------------------------------------------------*/
/*      CreateMicro:declaration d'un micro*/
/*      Entree:id utilisateur du micro à creer*/
/*      Sortie:TRUE si OK,FALSE sinon*/
/*------------------------------------------------------------*/
long SND_fn_lCreateMicroSound(void)
{
        long lRet=C_CREATEMICRO_FAILED;
#ifndef NO_ACP_SOUND
        /*MicroParam    par;*/
        pMICRO_DESCRIPTION pMicro;
 
        SND_fn_vEnterCriticalSectionThreadSnd();
 
#ifdef NB_MICRO_MAX
		if (g_iNbActiveMicros==NB_MICRO_MAX)
		{
			SND_M_DisplayError(E_uwSndSystemError,"Too many microphone");
 
	        SND_fn_vQuitCriticalSectionThreadSnd();
			return C_CREATEMICRO_FAILED;
		}
#endif
 
        g_iNbActiveMicros++;
 
        pMicro=SND_fn_pvMallocSndEx(E_ucSndBlockMain,sizeof(MICRO_DESCRIPTION));
        SNDLST2_M_DynamicInitElement(pMicro);
        SNDLST2_M_DynamicAddTail(&micros_sound.pList,pMicro);
 
        pMicro->sndId=SND_fn_lCreateMicroSnd(NULL);
        lRet=(long)pMicro;
 
        #ifdef SUPERVISATER
        dbgSND_fn_vAddMicro(lRet);
        #endif
 
        SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
        return lRet;
}
 
/*------------------------------------------------------------*/
/*      DestroyMicro:destruction d'un micro*/
/*      Entree:id utilisateur du micro à detruire*/
/*      Sortie:neant*/
/*------------------------------------------------------------*/
void SND_fn_vDestroyMicroSound(long Id)
{
#ifndef NO_ACP_SOUND
        SND_fn_vEnterCriticalSectionThreadSnd();
 
        g_iNbActiveMicros--;
        
        SNDLST2_M_DynamicIsolate((pMICRO_DESCRIPTION)Id);
        SND_fn_vDestroyMicroSnd(((pMICRO_DESCRIPTION)Id)->sndId);
        SND_fn_vFreeSndEx(E_ucSndBlockMain,(pMICRO_DESCRIPTION)Id);
 
        #ifdef SUPERVISATER
        dbgSND_fn_vKillMicro(Id);
        #endif
 
        SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}
 
/*------------------------------------------------------------*/
/*      DestroyAllMicro:destruction de tous les micros*/
/*      Entree:neant*/
/*      Sortie:neant*/
/*------------------------------------------------------------*/
void SND_fn_vDestroyAllMicroSound(void)
{
#ifndef NO_ACP_SOUND
        pMICRO_DESCRIPTION pMicro,pMicroNext;
        int i;
 
        SND_fn_vEnterCriticalSectionThreadSnd();
 
        g_iNbActiveMicros=0;
        
        SNDLST2_M_DynamicForEachMovingElementOf(&micros_sound.pList,pMicro,pMicroNext,i)
        {
                #ifdef SUPERVISATER
                dbgSND_fn_vKillMicro((long)pMicro);
                #endif
                SND_fn_vDestroyMicroSnd(pMicro->sndId);
                                SNDLST2_M_DynamicIsolate(pMicro);
                                SND_fn_vFreeSndEx(E_ucSndBlockMain,pMicro);
        }
 
        SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}
 
/*-----------------------------------------------------------*/
/*      SetRetMicroSound:initialiser les fonction RetMicroSound*/
/*      Entree:ptrfct=pointeur sur les pfn*/
/*-----------------------------------------------------------*/
void SND_fn_vSetRetMicroSound(tdstAllRetMicroSound *ptrfct)
{
#ifndef NO_ACP_SOUND
        SND_fn_vEnterCriticalSectionThreadSnd();
 
        check_micro_fct();
 
        memcpy(&g_st_pfnRetMicroSound,ptrfct,sizeof(tdstAllRetMicroSound));
 
        SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}
 
/*-----------------------------------------------------------------*/
/*      Ajoût d'une nouvelle ligne de volume*/
/*-----------------------------------------------------------------*/
long SND_fn_lAddVolumeLineSound(void)
{
#ifndef NO_ACP_SOUND
        ptdstVolumeLine pLine;
 
        SND_fn_vEnterCriticalSectionThreadSnd();
 
        if (!nb_volume_lines)
                SNDLST2_M_DynamicInitAnchor(&(g_VolumeLines.pList));
 
        pLine=SND_fn_pvMallocSndEx(E_ucSndBlockMain,sizeof(tdstVolumeLine));
        memset(pLine,0,sizeof(tdstVolumeLine));
        SNDLST2_M_DynamicInitElement(pLine);
        SNDLST2_M_DynamicAddTail(&(g_VolumeLines.pList),pLine);
        pLine->lVol=C_SOUNDVOL_MAXI;
 
        nb_volume_lines++;
 
        SND_fn_vQuitCriticalSectionThreadSnd();
 
                #ifdef SUPERVISATER
                dbgSND_fn_vAddVolumeLine((long)pLine);
                #endif
 
        return (long)pLine;
#else
    return SND_C_LINE_FANTOME;
#endif /*NO_ACP_SOUND*/
}

#ifndef NO_ACP_SOUND
 
/*update function pointers for a sound object type*/
void fn_vUpdateTypeObjectSoundInfos(tdstAllRetObjectSound *ptrfct,tdstAllRetObjectSound *new_ptrfct)
{
	/*first copy default pointers values */
	memcpy(ptrfct,&g_astTypeObjectSoundInfosDefault,sizeof(tdstAllRetObjectSound));
 
	/*second update non NULL pointer*/
#ifdef MAXI_SCHEMMING
	/*this first method is quite fast and light sized, but could be dangerous for som target*/
	for (i=0;i<sizeof(tdstAllRetObjectSound)/sizeof(td_pfn_rRetSoundCoord);i++)
		if  (*((td_pfn_rRetSoundCoord)new_ptrfct+i)!=NULL)
			*((td_pfn_rRetSoundCoord)ptr_fct+i)=*((td_pfn_rRetSoundCoord)new_ptrfct+i);
#else
	/*exact method, but quite big sized source code*/
	if (new_ptrfct->X!=NULL)
		ptrfct->X=new_ptrfct->X;
	if (new_ptrfct->Y!=NULL)
		ptrfct->Y=new_ptrfct->Y;
	if (new_ptrfct->Z!=NULL)
		ptrfct->Z=new_ptrfct->Z;
	if (new_ptrfct->VX!=NULL)
		ptrfct->VX=new_ptrfct->VX;
	if (new_ptrfct->VY!=NULL)
		ptrfct->VY=new_ptrfct->VY;
	if (new_ptrfct->VZ!=NULL)
		ptrfct->VZ=new_ptrfct->VZ;
	if (new_ptrfct->REVERB!=NULL)
		ptrfct->REVERB=new_ptrfct->REVERB;
	if (new_ptrfct->ExtraCoef!=NULL)
		ptrfct->ExtraCoef=new_ptrfct->ExtraCoef;
	if (new_ptrfct->Switch!=NULL)
		ptrfct->Switch=new_ptrfct->Switch;
	if (new_ptrfct->MicroLink!=NULL)
		ptrfct->MicroLink=new_ptrfct->MicroLink;
#endif
}

/*
 *=============================================================================
 *	fn_vSetDefaultRetChannelSound
 *
 *  Description : Initialize default Channel callback function for an object type 
 *=============================================================================
 *  Input 
 *			None
 *
 *  Output : None
 *
 *=============================================================================
 *  Creation date :			            Author :             
 *=============================================================================
 *  Modification date :	02/06/99	    Author : Pascal Lalancette
 *  Modifications : Add default channel callback on new sound type
 *=============================================================================
 */
void fn_vSetDefaultRetChannelSound(long type)
{
	 memcpy(&g_d_pstTypeObjectSoundInfos[type].pfnRetChannelSound, &g_astChannelSoundInfosDefault,sizeof(tdstAllRetChannelSound));
}

#endif
 
#ifdef DREAMCAST
/*	SND_fn_vSetNbObjectTypeSound ---------------------------------------------------------------------------------------------
Purpose: This function must be called previously to SND_fn_lAddObjectTypeSound. It allocates memory for Object Type Sound,
		whatever that means!
----------------------------------------------------------------------------------------------------------------------------*/
void	SND_fn_vSetNbObjectTypeSound(long p_lNbObjectTypeSound)
{
#ifndef NO_ACP_SOUND

	g_lNbMaxObjectType = p_lNbObjectTypeSound+1;
	g_d_pstTypeObjectSoundInfos = SND_fn_pvMallocSndEx(E_ucSndBlockMain,g_lNbMaxObjectType*sizeof(tdstTypeObjectInfos));
	if (g_d_pstTypeObjectSoundInfos == NULL)
	{
 		Erm_M_ClearLastError ( C_ucErmDefaultChannel );
		Erm_M_UpdateLastError( Snd, C_ucErmDefaultChannel, E_uwSndMemoryAllocError, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, "Malloc allocation");
	}

	nb_object_type = 0;
	SND_fn_lAddObjectTypeSound2(&g_astTypeObjectSoundInfosDefault,SND_C_LINE_FANTOME);

#endif	/*NO_ACP_SOUND*/
}
#endif /*DREAMCAST*/

/*
 *=============================================================================
 *	SND_fn_lAddObjectTypeSound2
 *
 *  Description : Create/register a new sound object type
 *=============================================================================
 *  Input 
 *			ptrfct: Function pointers associated with the new type
 *			lLine : Volume line to assosiate to this new object type
 *
 *  Output : Volume line Id
 *
 *=============================================================================
 *  Creation date :			            Author :             
 *=============================================================================
 *  Modification date :	02/06/99	    Author : Pascal Lalancette
 *  Modifications : Add default channel callback on new sound type
 *=============================================================================
 */
long SND_fn_lAddObjectTypeSound2(tdstAllRetObjectSound *ptrfct,long lLine)
{       
#ifndef NO_ACP_SOUND
        int id_type;
        ptdstVolumeLine pLine;
 
        SND_fn_vEnterCriticalSectionThreadSnd();

#ifndef DREAMCAST 
        if (nb_object_type==0)
        {/*type #0 is a particluar one (default type=FANTOME) = done only once during the game*/
                id_type=0;
                g_d_pstTypeObjectSoundInfos=SND_fn_pvMallocSndEx(E_ucSndBlockMain,sizeof(tdstTypeObjectInfos));
				nb_object_type=0;
		}
        else
        {/*add a new type*/
                id_type=nb_object_type;
                g_d_pstTypeObjectSoundInfos=(tdstTypeObjectInfos*)SND_fn_pvReAllocSndEx(E_ucSndBlockMain,g_d_pstTypeObjectSoundInfos,(id_type+1)*sizeof(tdstTypeObjectInfos)); 
        }
#else
		
		/* test if enough memory has been allocated by SND_fn_vSetNbObjectTypeSound*/
		assert( g_d_pstTypeObjectSoundInfos != NULL );
		assert( g_lNbMaxObjectType > nb_object_type);

        id_type=nb_object_type;
#endif /*DREAMCAST*/

		/*init some fields*/
        memset(&g_d_pstTypeObjectSoundInfos[id_type],0,sizeof(tdstTypeObjectInfos));
		g_d_pstTypeObjectSoundInfos[id_type].pstLastEvent=SND_C_RES_FANTOME_PTR;
        SNDLST2_M_DynamicInitAnchor(&g_d_pstTypeObjectSoundInfos[id_type].pListVolumeChanged);
        g_d_pstTypeObjectSoundInfos[id_type].lVolume=C_SOUNDVOL_MAXI;
        
		/*init volume line to be used for this new type*/
		if (lLine!=SND_C_LINE_FANTOME) 
        {
                pLine=(ptdstVolumeLine)lLine;
                g_d_pstTypeObjectSoundInfos[id_type].pstVolumeLine=pLine;
        }
        else
                g_d_pstTypeObjectSoundInfos[id_type].pstVolumeLine=NULL;
        
		nb_object_type++;
 
		/*update function pointers*/
		fn_vUpdateTypeObjectSoundInfos(&g_d_pstTypeObjectSoundInfos[id_type].pfnRetObjectSound,ptrfct);

		//Use default pointer for channel until they are set by the user
		fn_vSetDefaultRetChannelSound(id_type);
 
        SND_fn_vQuitCriticalSectionThreadSnd();
 
        return id_type;
#else
    return -1;
#endif /*NO_ACP_SOUND*/
}
 
/*-----------------------------------------------------------*/
/*      SND_fn_vSetRetObjectTypeSound:change functions pointers associated with a previously created sound object type*/
/*      Parameter:type (IN)= sound obejct type to be changed (should have been created by previous call to SND_fn_lAddObjectTypeSound2)*/
/*			ptrfct (IN)=new function pointers associated with this type*/
/*-----------------------------------------------------------*/
void SND_fn_vSetRetObjectTypeSound(long type,tdstAllRetObjectSound *ptrfct)
{
#ifndef NO_ACP_SOUND
    SND_fn_vEnterCriticalSectionThreadSnd();
 
	if (type<0 || type>=nb_object_type)
		SND_M_DisplayError(E_uwSndSystemError,"Invalid sound ovejct type");
	else
	{
		fn_vUpdateTypeObjectSoundInfos(&g_d_pstTypeObjectSoundInfos[type].pfnRetObjectSound,ptrfct);
	}
 
	SND_fn_vQuitCriticalSectionThreadSnd();
#endif
}
 
/*-----------------------------------------------------------*/
/*      SND_fn_vSetInfoForTypeSound:associated a "Info Callback funciton" qwith a previously created sound object type*/
/*		(this optionnal function return a czString for deug about sound object)*/
/*      Parameter:type (IN)= sound obejct type to be associated with this function (should have been created by previous call to SND_fn_lAddObjectTypeSound2)*/
/*			pfnCopy (IN)=function pointers associated with this type*/
/*-----------------------------------------------------------*/
void SND_fn_vSetInfoForTypeSound(long type,td_pfn_vCopyString pfnCopy)
{
#ifndef NO_ACP_SOUND
        if (type>=0 && type<nb_object_type)
        {
                g_d_pstTypeObjectSoundInfos[type].pfnInfoObject=pfnCopy;
        }
#endif
}
 
void SND_fn_vGetInfoForObjectSound(long id,long type,char* str,long size_ptr)
{
#ifndef NO_ACP_SOUND
        if (g_d_pstTypeObjectSoundInfos[type].pfnInfoObject)
        {
                (*g_d_pstTypeObjectSoundInfos[type].pfnInfoObject)(id,str,size_ptr);
        }
        else
                strncpy(str,"no info",size_ptr);
#endif
}
 
void SND_fn_vSetRollOffFunctionForTypeSound(long type,td_pfn_bRetRollOffFactor fct)
{
#ifndef NO_ACP_SOUND
        if (type>=0 && type<nb_object_type)
        {
                g_d_pstTypeObjectSoundInfos[type].pfnRollOff=fct;
        }
#endif
}
 
 
/*-----------------------------------------------------------------*/
/*      Reglages des lignes de volume*/
/*-----------------------------------------------------------------*/
long SND_fn_lGetVolumeLineSound(long lLine)
{
#ifndef NO_ACP_SOUND
        ptdstVolumeLine pLine;
 
        if (lLine!=SND_C_LINE_FANTOME)
        {
                pLine=(ptdstVolumeLine)lLine;
                return pLine->lVol;
        }
        else
#endif
                return C_SOUNDVOL_MAXI;
}
 
void SND_fn_vSetVolumeLineSound(long lLine,long lNewVolume)
{
#ifndef NO_ACP_SOUND
        ptdstVolumeLine pLine;
 
        if (lLine!=SND_C_LINE_FANTOME)
        {
                pLine=(ptdstVolumeLine)lLine;
                /*if (pLine!=NULL)*/
                {
                        pLine->lVol=lNewVolume;
                        fn_vRajAllVolumeForLine(pLine);
 
                                                #ifdef SUPERVISATER
                                                dbgSND_fn_vSetVolumeLine((long)pLine,lNewVolume);
                                                #endif
                }
        }
#endif
}
 
 
 
/*----------------------------------*/
/* Pause/resume every sounds		*/
/*----------------------------------*/
void SND_fn_vPauseSound(void)
{
#ifndef NO_ACP_SOUND
        if (g_bInitDoneSound)
        {
                SND_fn_vEnterCriticalSectionThreadSnd();
 
                SND_fn_vPauseAllSnd();
 
                SND_fn_vQuitCriticalSectionThreadSnd();
        }
#endif /*NO_ACP_SOUND*/
}
 
void SND_fn_vResumeSound(void)
{
#ifndef NO_ACP_SOUND
        if (g_bInitDoneSound)
        {
                SND_fn_vEnterCriticalSectionThreadSnd();
 
                SND_fn_vResumeAllSnd();
 
                SND_fn_vQuitCriticalSectionThreadSnd();
        }
#endif /*NO_ACP_SOUND*/
}

/*----------------------------------*/
/* Pause/resume for one object		*/
/*----------------------------------*/
void SND_fn_vPauseObjectSound(long indice,long type)
{
#ifndef NO_ACP_SOUND
        pASSOCIATION_DESCRIPTION pAsso;
        int i;

        if (g_bInitDoneSound)
        {
                SND_fn_vEnterCriticalSectionThreadSnd();
 
				SNDLST2_M_DynamicForEachElementOf(&association.pList,pAsso,i)
				{/*for each asso*/
					if (pAsso->bValid)
					{/*check if asso is valid*/
						if (pAsso->indice==indice && pAsso->type==type)
						{/*found an object*/
							SND_fn_vPauseSnd(pAsso->voice);
						}
					}
				}
				
                SND_fn_vQuitCriticalSectionThreadSnd();
        }
#endif /*NO_ACP_SOUND*/
}

void SND_fn_vResumeObjectSound(long indice,long type)
{
#ifndef NO_ACP_SOUND
        pASSOCIATION_DESCRIPTION pAsso;
        int i;

        if (g_bInitDoneSound)
        {
                SND_fn_vEnterCriticalSectionThreadSnd();
 
				SNDLST2_M_DynamicForEachElementOf(&association.pList,pAsso,i)
				{/*for each asso*/
					if (pAsso->bValid)
					{/*check if asso is valid*/
						if (pAsso->indice==indice && pAsso->type==type)
						{/*found an object*/
							SND_fn_vResumeSnd(pAsso->voice);
						}
					}
				}
				
                SND_fn_vQuitCriticalSectionThreadSnd();
        }
#endif /*NO_ACP_SOUND*/
}

/*----------------------------------*/
/* Pause/resume for one type		*/
/*----------------------------------*/
void SND_fn_vPauseTypeSound(long type)
{
#ifndef NO_ACP_SOUND
        pASSOCIATION_DESCRIPTION pAsso;
        int i;

        if (g_bInitDoneSound)
        {
                SND_fn_vEnterCriticalSectionThreadSnd();
 
				SNDLST2_M_DynamicForEachElementOf(&association.pList,pAsso,i)
				{/*for each asso*/
					if (pAsso->bValid)
					{/*check if asso is valid*/
						if (pAsso->type==type)
						{/*found an object*/
							SND_fn_vPauseSnd(pAsso->voice);
						}
					}
				}
				
                SND_fn_vQuitCriticalSectionThreadSnd();
        }
#endif /*NO_ACP_SOUND*/
}

void SND_fn_vResumeTypeSound(long type)
{
#ifndef NO_ACP_SOUND
        pASSOCIATION_DESCRIPTION pAsso;
        int i;

        if (g_bInitDoneSound)
        {
                SND_fn_vEnterCriticalSectionThreadSnd();
 
				SNDLST2_M_DynamicForEachElementOf(&association.pList,pAsso,i)
				{/*for each asso*/
					if (pAsso->bValid)
					{/*check if asso is valid*/
						if (pAsso->type==type)
						{/*found an object*/
							SND_fn_vResumeSnd(pAsso->voice);
						}
					}
				}
				
                SND_fn_vQuitCriticalSectionThreadSnd();
        }
#endif /*NO_ACP_SOUND*/
}

/*--------------------------------------*/
/* Pause/resume for all types but one	*/
/*--------------------------------------*/
void SND_fn_vPauseButOneTypeSound(long type)
{
#ifndef NO_ACP_SOUND
        pASSOCIATION_DESCRIPTION pAsso;
        int i;

        if (g_bInitDoneSound)
        {
                SND_fn_vEnterCriticalSectionThreadSnd();
 
				SNDLST2_M_DynamicForEachElementOf(&association.pList,pAsso,i)
				{/*for each asso*/
					if (pAsso->bValid)
					{/*check if asso is valid*/
						if (pAsso->type!=type)
						{/*found an object*/
							SND_fn_vPauseSnd(pAsso->voice);
						}
					}
				}
				
                SND_fn_vQuitCriticalSectionThreadSnd();
        }
#endif /*NO_ACP_SOUND*/
}

void SND_fn_vResumeButOneTypeSound(long type)
{
#ifndef NO_ACP_SOUND
        pASSOCIATION_DESCRIPTION pAsso;
        int i;

        if (g_bInitDoneSound)
        {
                SND_fn_vEnterCriticalSectionThreadSnd();
 
				SNDLST2_M_DynamicForEachElementOf(&association.pList,pAsso,i)
				{/*for each asso*/
					if (pAsso->bValid)
					{/*check if asso is valid*/
						if (pAsso->type!=type)
						{/*found an object*/
							SND_fn_vResumeSnd(pAsso->voice);
						}
					}
				}
				
                SND_fn_vQuitCriticalSectionThreadSnd();
        }
#endif /*NO_ACP_SOUND*/
}


 
/*relache-reprise à chaud des drivers bas-niveaux*/
void SND_fn_vForceReleaseDriverSound()
{
#ifndef NO_ACP_SOUND
        SND_fn_vForceReleaseDriverSnd();
#endif /*NO_ACP_SOUND*/
}
 
void SND_fn_vForceRestoreDriverSound()
{
#ifndef NO_ACP_SOUND
        SND_fn_vForceRestoreDriverSnd();
#endif /*NO_ACP_SOUND*/
}
 
SndBool SND_fn_bReleaseDriverSound()
{
#ifndef NO_ACP_SOUND
        if (g_bInitDoneSound)
        {
                if (SND_fn_bEnterCriticalSectionForDriverThreadSnd())
                                {
                                        SND_fn_vReleaseDriverSnd();
                                        SND_fn_vQuitCriticalSectionThreadSnd();
 
                                        return TRUE;
                                }
        }
#endif
                return FALSE;
}
 
SndBool SND_fn_bRestoreDriverSound()
{
#ifndef NO_ACP_SOUND
        if (g_bInitDoneSound)
        {
                if (SND_fn_bEnterCriticalSectionForDriverThreadSnd())
                                {
                                        SND_fn_vRestoreDriverSnd();
                                        SND_fn_vQuitCriticalSectionThreadSnd();
 
                                        return TRUE;
                                }
        }
#endif
                return FALSE;
}
 
void SND_fn_vReleaseDriverSound(void)
{
        SND_fn_bReleaseDriverSound();
}
 
void SND_fn_vRestoreDriverSound(void)
{
        SND_fn_bRestoreDriverSound();
}
 
 
/*reglage des volumes gene*/
long SND_fn_lGetVolumeSound()
{
#ifndef NO_ACP_SOUND
        return (long)SND_fn_ucGetSoundVolumeSnd();
#else
                return 0;
#endif
}
 
void SND_fn_vSetVolumeSound(long vol)
{
#ifndef NO_ACP_SOUND
        SND_fn_vSetSoundVolumeSnd((unsigned char)vol);
#endif
}
 
void SND_fn_vSetStereoSound(SndBool active)
{
#ifndef NO_ACP_SOUND
        SND_fn_vSetStereoSnd(active);
#endif
}
 
SndBool SND_fn_bGetStereoSound(void)
{
#ifndef NO_ACP_SOUND
        return SND_fn_bGetStereoSnd();
#else
                return FALSE;
#endif
}
 
SndBool SND_fn_bIsMusicPlayingSound(void)
{
#ifndef NO_ACP_SOUND
        return SND_fn_bIsMusicPlayingSnd();
#else
                return FALSE;
#endif
}
 
void SND_fn_vSetReverseStereoSound(SndBool active)
{
#ifndef NO_ACP_SOUND
        SND_fn_vSetReverseStereoSnd(active) ;
#endif
}
 
SndBool SND_fn_bGetReverseStereoSound(void)
{
#ifndef NO_ACP_SOUND
        return SND_fn_bGetReverseStereoSnd();
#else
                return FALSE;
#endif
}
 
 
 
/*---------------------------------------------------------*/
/*      GetTargetLabel: retourne le label designant la tareget*/
/*      Entree: name=nom cible*/
/*              nb_char=taille maxi de la cible*/
/*----------------------------------------------------------*/
void SND_fn_vGetTargetLabelSound(char* name,int nb_char)
{
#ifndef NO_ACP_SOUND
        SND_fn_vGetTargetLabelSnd(name,nb_char);
#endif
}
 
void SND_fn_vSetupTargetSound(void)
{
#ifndef NO_ACP_SOUND
        SND_fn_vSetupTargetSnd();
#endif
}
 
SndBool SND_fn_bCanSetupTargetSound(void)
{
#ifndef NO_ACP_SOUND
        return SND_fn_bCanSetupTargetSnd();
#else
        return FALSE;
#endif
}
 
 
long SND_fn_lCreateNewBufferSound(unsigned long nb_samples,unsigned short uwResolution,unsigned short uwNbChannels,unsigned long ulFreq,SoundParam* par,td_pfn_vRefreshBufferClient callback,long user_id)
{
#ifndef DISABLE_BUFFER_CLIENT
#ifndef NO_ACP_SOUND
        return SND_fn_lCreateNewBufferSnd(nb_samples,uwResolution,uwNbChannels,ulFreq,par,callback,user_id);
#else
        return SND_C_EVT_FAILED;
#endif
#else
        return SND_C_EVT_FAILED;
#endif /* DISABLE_BUFFER_CLIENT*/
}
 
void    SND_fn_vDeleteBufferSound(long id_buffer)
{
#ifndef DISABLE_BUFFER_CLIENT
#ifndef NO_ACP_SOUND
        SND_fn_vDeleteBufferSnd(id_buffer);
#endif
#endif /* DISABLE_BUFFER_CLIENT*/
}
 
void SND_fn_vPauseBufferSound(long id_buffer)
{
#ifndef DISABLE_BUFFER_CLIENT
#ifndef NO_ACP_SOUND
        SND_fn_vPauseBufferSnd(id_buffer);
#endif
#endif /* DISABLE_BUFFER_CLIENT*/
}
 
void SND_fn_vResumeBufferSound(long id_buffer)
{
#ifndef DISABLE_BUFFER_CLIENT
#ifndef NO_ACP_SOUND
        SND_fn_vResumeBufferSnd(id_buffer);
#endif
#endif /* DISABLE_BUFFER_CLIENT*/
}
 
SndReal SND_fn_rGetPosBufferSound(long id_buffer)
{
#ifndef DISABLE_BUFFER_CLIENT
#ifndef NO_ACP_SOUND
        return SND_fn_rGetPosBufferSnd(id_buffer);
#else
        return SND_C_POS_UNKNOWN;
#endif
#else
        return SND_C_POS_UNKNOWN;
#endif /* DISABLE_BUFFER_CLIENT*/
}
 
long SND_fn_lCreateNewBufferExSound(SND_tdstFormat* pformat,SND_tdstCallback* pCallback,SoundParam* par,long user_id)
{
#ifndef DISABLE_BUFFER_CLIENT
#ifndef NO_ACP_SOUND
        return SND_fn_lCreateNewBufferExSnd(pformat,pCallback,par,user_id);
#else
        return SND_C_EVT_FAILED;
#endif
#else
        return SND_C_EVT_FAILED;
#endif /* DISABLE_BUFFER_CLIENT*/
}
 
long SND_fn_lGetPosBufferExSound(long id_buffer)
{
#ifndef DISABLE_BUFFER_CLIENT
#ifndef NO_ACP_SOUND
        return SND_fn_lGetPosBufferExSnd(id_buffer);
#else
        return SND_C_POS_UNKNOWN;
#endif
#else
        return SND_C_POS_UNKNOWN;
#endif /* DISABLE_BUFFER_CLIENT*/
}
 
long SND_fn_lPushBufferExSound(long id_buffer,SND_tdstStackBuffer* pStack)
{
#ifndef DISABLE_BUFFER_CLIENT
#ifndef NO_ACP_SOUND
        return SND_fn_lPushBufferExSnd(id_buffer,pStack);
#else
        return SND_C_EVT_FAILED;
#endif
#else
        return SND_C_EVT_FAILED;
#endif /* DISABLE_BUFFER_CLIENT*/
}
 
void SND_fn_vSetParamBufferSound(long id_buffer,SoundParam* par)
{
#ifndef DISABLE_BUFFER_CLIENT
#ifndef NO_ACP_SOUND
        SND_fn_vSetParamBufferSnd(id_buffer,par);
#endif
#endif /* DISABLE_BUFFER_CLIENT*/
}
 
 
long SND_fn_lGetSwitchIndice(long objecttype,long objectid,tduRefRes uRes)
{
#ifndef NO_ACP_SOUND
        return (g_d_pstTypeObjectSoundInfos[objecttype].pfnRetObjectSound.Switch)(objectid,uRes.pstPtr->uRes.stSwitch.lTypeSwitch);
#else
        return 0;
#endif
}
 
long    SND_fn_lGetNbVoiceOptimumSound()
{
#ifndef NO_ACP_SOUND
        return SND_fn_lGetNbVoiceOptimumSnd();
#else
        return 0;
#endif
}
 
long    SND_fn_lGetNbVoiceWishedSound()
{
#ifndef NO_ACP_SOUND
        return SND_fn_lGetNbVoiceWishedSnd();
#else
        return 0;
#endif
}
 
void    SND_fn_vSetNbVoiceWishedSound(long nb)
{
#ifndef NO_ACP_SOUND
        SND_fn_vSetNbVoiceWishedSnd(nb);
#endif
}
 
/********************************************************************
        Public function for object's volume management
***********************************************************************/
/*------------------------------------------------------------*/
/*      Change volume for one object*/
/*      Parameters:*/
/*              indice=object's indice*/
/*              type=object's sound type*/
/*              lNewVolume=nex volume (0 to 127)*/
/*------------------------------------------------------------*/
void SND_fn_vChangeVolumeSound(long indice,long type,long lNewVolume)
{
#ifndef NO_ACP_SOUND
    SND_fn_vEnterCriticalSectionThreadSnd();
 
    fn_vChangeVolumeForObject(indice,type,lNewVolume);
 
    SND_fn_vSynchroSound();
 
    SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}
 
void SND_fn_vResetVolumeSound(long indice,long type)
{
#ifndef NO_ACP_SOUND
    SND_fn_vEnterCriticalSectionThreadSnd();
 
	fn_vResetVolumeForObject(indice,type);
 
    SND_fn_vSynchroSound();
 
    SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}
 
long SND_fn_lGetVolumeObjectSound(long indice,long type)
{
#ifndef NO_ACP_SOUND
	long lVolume;

    SND_fn_vEnterCriticalSectionThreadSnd();
 
	lVolume=fn_lGetVolumeForObject(indice,type); 
 
    SND_fn_vQuitCriticalSectionThreadSnd();

	return lVolume;
#endif /*NO_ACP_SOUND*/
}

/*------------------------------------------------------------*/
/*      Change volume for all objects execpt one*/
/*      Parameters:*/
/*              indice=object's indice*/
/*              type=object's sound type*/
/*              lNewVolume=nex volume (0 to 127)*/
/*------------------------------------------------------------*/
void SND_fn_vChangeVolumeAllObjectButOneSound(long indice,long type,long lNewVolume)
{
#ifndef NO_ACP_SOUND
    pASSOCIATION_DESCRIPTION pAsso;
    int i;

	SND_fn_vEnterCriticalSectionThreadSnd();
 
    SNDLST2_M_DynamicForEachElementOf(&association.pList,pAsso,i)
    {/*for each asso*/
        if (pAsso->bValid)
			if ((pAsso->indice!=indice) && (pAsso->type!=type))
				fn_vChangeVolumeForObject(pAsso->indice,pAsso->type,lNewVolume);
	}
 
    SND_fn_vSynchroSound();
 
    SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}
 
void SND_fn_vResetVolumeAllObjectButOneSound(long indice,long type)
{
#ifndef NO_ACP_SOUND
    pASSOCIATION_DESCRIPTION pAsso;
    int i;

	SND_fn_vEnterCriticalSectionThreadSnd();
 
    SNDLST2_M_DynamicForEachElementOf(&association.pList,pAsso,i)
    {/*for each asso*/
        if (pAsso->bValid)
			if ((pAsso->indice!=indice) && (pAsso->type!=type))
				fn_vResetVolumeForObject(pAsso->indice,pAsso->type);
	}
 
    SND_fn_vSynchroSound();
 
    SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}
 
/*------------------------------------------------------------*/
/*      Change volume for one object-type*/
/*      Parameters:*/
/*              type=object's sound type*/
/*              lNewVolume=nex volume (0 to 127)*/
/*------------------------------------------------------------*/
void SND_fn_vChangeVolumeTypeSound(long type,long lNewVolume)
{
#ifndef NO_ACP_SOUND
    SND_fn_vEnterCriticalSectionThreadSnd();
 
    fn_vChangeVolumeForType(type,lNewVolume);
 
	SND_fn_vSynchroSound();
 
    SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}
 
void SND_fn_vResetVolumeTypeSound(long type)
{
#ifndef NO_ACP_SOUND
    SND_fn_vEnterCriticalSectionThreadSnd();
 
    fn_vChangeVolumeForType(type,C_SOUNDVOL_MAXI);
 
	SND_fn_vSynchroSound();
 
    SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}
 
long SND_fn_lGetVolumeTypeSound(long type)
{
#ifndef NO_ACP_SOUND
	long lVolume;

    SND_fn_vEnterCriticalSectionThreadSnd();
 
	lVolume=fn_lGetVolumeForType(type); 
 
    SND_fn_vQuitCriticalSectionThreadSnd();

	return lVolume;
#endif /*NO_ACP_SOUND*/
}

/*------------------------------------------------------------*/
/*      Change volume for every object-type but one*/
/*      Parameters:*/
/*              type=object-type to not change volume of*/
/*              lNewVolume=nex volume (0 to 127)*/
/*------------------------------------------------------------*/
void SND_fn_vChangeVolumeButOneTypeSound(long type,long lNewVolume)
{
#ifndef NO_ACP_SOUND
        int i;
 
    SND_fn_vEnterCriticalSectionThreadSnd();
 
        for (i=0;i<nb_object_type;i++)
                if (i!=type) 
                        fn_vChangeVolumeForType(i,lNewVolume);
 
	SND_fn_vSynchroSound();
 
    SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}
 
void SND_fn_vResetVolumeButOneTypeSound(long type)
{
#ifndef NO_ACP_SOUND
        int i;
 
    SND_fn_vEnterCriticalSectionThreadSnd();
 
        for (i=0;i<nb_object_type;i++)
                if (i!=type) 
                        fn_vResetVolumeForType(i);
 
    SND_fn_vSynchroSound();
 
    SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}

/*------------------------------------------------------------*/
/*      Change volume for every objects of a specific type*/
/*      Parameters:*/
/*              type=object-type to change volume of*/
/*              lNewVolume=nex volume (0 to 127)*/
/*------------------------------------------------------------*/
void SND_fn_vChangeVolumeAllObjectSound(long type,long lNewVolume)
{
#ifndef NO_ACP_SOUND
    pASSOCIATION_DESCRIPTION pAsso;
    int i;

	SND_fn_vEnterCriticalSectionThreadSnd();
 
    SNDLST2_M_DynamicForEachElementOf(&association.pList,pAsso,i)
    {/*for each asso*/
        if (pAsso->bValid)
			if (pAsso->type==type)
				fn_vChangeVolumeForObject(pAsso->indice,pAsso->type,lNewVolume);
	}
 
    SND_fn_vSynchroSound();
 
    SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}

void SND_fn_vResetVolumeAllObjectSound(long type)
{
#ifndef NO_ACP_SOUND
    pASSOCIATION_DESCRIPTION pAsso;
    int i;

	SND_fn_vEnterCriticalSectionThreadSnd();
 
    SNDLST2_M_DynamicForEachElementOf(&association.pList,pAsso,i)
    {/*for each asso*/
        if (pAsso->bValid)
			if (pAsso->type==type)
				fn_vResetVolumeForObject(pAsso->indice,pAsso->type);
	}
 
    SND_fn_vSynchroSound();
 
    SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}

/*------------------------------------------------------------*/
/*      Change volume for every objects of a specific type*/
/*      Parameters:*/
/*              type=object-type to change volume of*/
/*              lNewVolume=nex volume (0 to 127)*/
/*------------------------------------------------------------*/
void SND_fn_vChangeVolumeAllTypeSound(long lNewVolume)
{
#ifndef NO_ACP_SOUND
        int i;
 
    SND_fn_vEnterCriticalSectionThreadSnd();
 
	for (i=0;i<nb_object_type;i++)
		fn_vChangeVolumeForType(i,lNewVolume);
 
    SND_fn_vSynchroSound();
 
    SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}

void SND_fn_vResetVolumeAllTypeSound(void)
{
#ifndef NO_ACP_SOUND
    int i;
 
    SND_fn_vEnterCriticalSectionThreadSnd();
 
	for (i=0;i<nb_object_type;i++)
		fn_vResetVolumeForType(i);
 
    SND_fn_vSynchroSound();
 
    SND_fn_vQuitCriticalSectionThreadSnd();
#endif /*NO_ACP_SOUND*/
}
 
/*--------------------------------------------------*/
/*      SND_fn_uGenerateEventPlaySound: dynamically create a SoundEvent Play from data loaded by client*/
/*      Parameters:*/
/*              data: pointer onto data*/
/*              pformat: descruiption of data*/
/*              loop: TRUE if ressource should loop*/
/*      Return:*/
/*              new created event Play*/
/*---------------------------------------------------*/
SND_tduRefEvt SND_fn_uGenerateEventPlaySound(void* data,SND_tdstFormat* pformat,SndBool loop)
{
#ifndef NO_ACP_SOUND
        SND_tduRefEvt   uEvt;
 
		if (g_bInitDoneSound)
		{
			uEvt.pstPtr=SND_fn_pvMallocSndEx(E_ucSndBlockMain,sizeof(SND_tdstBlockEvent));
			memset(uEvt.pstPtr,0,sizeof(SND_tdstBlockEvent));
 
			uEvt.pstPtr->eType=EVT_SON_PLAY;                
			uEvt.pstPtr->bStopable=TRUE;
			uEvt.pstPtr->bDynamic=TRUE;
 
			uEvt.pstPtr->uParams.stPlay.uResource=SND_fn_uGenerateResourceSnd(data,pformat,loop);
 
			return uEvt;
		}
		else
		{
			snd_assert(FALSE);//you should not call this function before SND_fn_vInitSound
			return SND_EVT_FANTOME;
		}
#else
		return SND_EVT_FANTOME;
#endif /*NO_ACP_SOUND*/
}
 
/*--------------------------------------------------*/
/*      SND_fn_uGenerateEventStopSound: dynamically create a SoundEvent Stop from another SoundEvent Play*/
/*      Parameters:*/
/*              event: event Play*/
/*      Return:*/
/*              new created event Stop*/
/*---------------------------------------------------*/
SND_tduRefEvt SND_fn_uGenerateEventStopSound(SND_tduRefEvt event)
{
#ifndef NO_ACP_SOUND
        SND_tduRefEvt uEvt;
 
		if (g_bInitDoneSound)
		{
			uEvt.pstPtr=SND_fn_pvMallocSndEx(E_ucSndBlockMain,sizeof(SND_tdstBlockEvent));
			memset(uEvt.pstPtr,0,sizeof(SND_tdstBlockEvent));
 
			uEvt.pstPtr->eType=EVT_SON_STOP;                
			uEvt.pstPtr->uParams.stStop.uEvt=event;
			uEvt.pstPtr->bStopable=TRUE;
			uEvt.pstPtr->bDynamic=TRUE;
 
			return uEvt;
		}
		else
		{
			snd_assert(FALSE);//you should not call this function before SND_fn_vInitSound
			return SND_EVT_FANTOME;
		}
#else
		return SND_EVT_FANTOME;
#endif /*NO_ACP_SOUND*/
}
 
/*--------------------------------------------------*/
/*      SND_fn_vDestroyEventSound: destroy a event */
/*              previously created by SND_fn_uGenerateEventPlaySound or*/
/*      Parameters:*/
/*              event: event to destroy*/
/*---------------------------------------------------*/
void SND_fn_vDestroyEventSound(SND_tduRefEvt event)
{
#ifndef NO_ACP_SOUND
	if (event.pstPtr!=EVT_FANTOME_PTR)
	{
        switch (event.pstPtr->eType)
        {
        case EVT_SON_STOP:
                SND_fn_vFreeSndEx(E_ucSndBlockMain,event.pstPtr);
                break;
        case EVT_SON_PLAY:
                SND_fn_vDestroyResourceSnd(event.pstPtr->uParams.stPlay.uResource);
                SND_fn_vFreeSndEx(E_ucSndBlockMain,event.pstPtr);
                break;
        default:
                SND_M_DisplayError(E_uwSndInvalidTypeOfEvent,"");
                break;
        }
	}
#endif /*NO_ACP_SOUND*/
}
 
/*----------SNDREC*/
SndBool	SND_fn_bTestFormatRecordSound(SND_tdstFormat* pformat,int flags)
{
#if !defined(DISABLE_RECORD) && !defined(NO_ACP_SOUND)
	return SND_fn_bTestFormatRecordSnd(pformat,flags);
#else
	return FALSE;
#endif
}
 
long		SND_fn_lCreateBufferRecordSound(SND_tdstFormat* pformat,SND_tdstCallback* pCallback)
{
#if !defined(DISABLE_RECORD) && !defined(NO_ACP_SOUND)
	return SND_fn_lCreateBufferRecordSnd(pformat,pCallback);
#else
	return C_PLAY_FAILED;
#endif
}
 
SndBool	SND_fn_bIsBufferFullDuplexRecordSound(long id_buffer)
{
#if !defined(DISABLE_RECORD) && !defined(NO_ACP_SOUND)
	return SND_fn_bIsBufferFullDuplexRecordSnd(id_buffer);
#else
	return FALSE;
#endif
}
 
SndBool	SND_fn_bStartRecordSound(long id_buffer)
{
#if !defined(DISABLE_RECORD) && !defined(NO_ACP_SOUND)
	return SND_fn_bStartRecordSnd(id_buffer);
#else
	return FALSE;
#endif
}
 
void		SND_fn_vStopRecordSound(long id_buffer)
{
#if !defined(DISABLE_RECORD) && !defined(NO_ACP_SOUND)
	SND_fn_vStopRecordSnd(id_buffer);
#endif
}
 
SndBool	SND_fn_bIsWorkingRecordSound(long id_buffer)
{
#if !defined(DISABLE_RECORD) && !defined(NO_ACP_SOUND)
	return SND_fn_bIsWorkingRecordSnd(id_buffer);
#else
	return FALSE;
#endif
}
 
long SND_fn_lPushBufferToRecordSound(long id_buffer,void* ptr,int size_ptr)
{
#if !defined(DISABLE_RECORD) && !defined(NO_ACP_SOUND)
	return SND_fn_lPushBufferToRecordSnd(id_buffer,ptr,size_ptr);
#else
	return FALSE;
#endif
}
 
unsigned char SND_fn_ucGetInstantVuMeterRecordSound(void)
{
#if !defined(DISABLE_RECORD) && !defined(NO_ACP_SOUND)
	return SND_fn_ucGetInstantVuMeterRecordSnd();
#else
	return 0;
#endif
}
 
