reman3/Rayman_X/cpa/tempgrp/SND_OLD/src/sndrndom.c

403 lines
12 KiB
C

/*-------------------------------------------------------------------*/
/*! !*/
/*! Module SNDRNDOM.C: management of TYPE_RANDOM resources !*/
/*! !*/
/*-------------------------------------------------------------------*/
#include "SNDinc.h"
#include "sndres.h"
#include "sndrndom.h"
#include "sndplay.h"
#include "sndrnd.h"
/*#include "sndmem.h"*/
#ifndef NO_ACP_SOUND
typedef struct random_voice_ random_voice;
struct random_voice_{
long lLowVoice; /*voice of low-level resource*/
SndBool bValid; /*TRUE while voice is active*/
tduRefRes uRes;/*Random resource associated*/
};
#define C_NEVER_CHOOSEN -2
#define C_NOTHING_CHOOSEN -1
/*----------------------------------------------------------------------------------
Get the NON-random resource associated with a instance of RANDOM resource
-----------------------------------------------------------------------------------*/
tduRefRes SND_fn_tdGetEffectiveResourceRandom(tduRefRes res_random)
{
tdstRandomElement* pRandomElement;
tdstTypeRandomMem* pRandomList;
tduRefRes uRes;
int i;
int lElementChoosen=C_NOTHING_CHOOSEN;
int lPreviousElementChoosen,lPreviousResChoosen;
SndBool bFound;
SndReal rOffset;
uRes=res_random;
pRandomList=&(uRes.pstPtr->uRes.stRandom);
/*lPreviousElementChoosen is set to C_NEVER_CHOOSEN if any element can be chosen*/
/* otherwise, is set to the element wich can not be chosen*/
/*lPreviousResChoosen is set to C_NEVER_CHOOSEN if any res can be chosen*/
/* otherwise, is set to the res wich can not be chosen*/
/*element = res + NOTHING*/
lPreviousElementChoosen=C_NEVER_CHOOSEN;
lPreviousResChoosen=C_NEVER_CHOOSEN;
if (res_random.pstPtr->uRes.stRandom.lLastResChoosen>=0)
{
SNDLST2_M_StaticGetElementNumber(pRandomList,pRandomElement,res_random.pstPtr->uRes.stRandom.lLastResChoosen,i);
if (!pRandomElement->bCanBeChosenTwice)
lPreviousResChoosen=res_random.pstPtr->uRes.stRandom.lLastResChoosen;
}
if (res_random.pstPtr->uRes.stRandom.lLastElementChoosen>=0)
{
SNDLST2_M_StaticGetElementNumber(pRandomList,pRandomElement,res_random.pstPtr->uRes.stRandom.lLastElementChoosen,i);
if (!pRandomElement->bCanBeChosenTwice)
lPreviousElementChoosen=res_random.pstPtr->uRes.stRandom.lLastElementChoosen;
}
else
{
if ((res_random.pstPtr->uRes.stRandom.lLastElementChoosen==C_NOTHING_CHOOSEN) && (!res_random.pstPtr->uRes.stRandom.bNothingCanBeChosenTwice))
lPreviousElementChoosen=C_NOTHING_CHOOSEN;
}
/*random number*/
rOffset=SND_fn_rGetRandomSnd(C_SNDREAL_1);
bFound=FALSE;
if ((rOffset>=pRandomList->rProbNothing) || (lPreviousElementChoosen==C_NOTHING_CHOOSEN))
{/*"Silence/nothing" is not chosen -> run the list to find the good element*/
rOffset-=pRandomList->rProbNothing;
SNDLST2_M_StaticForEachElementOf(pRandomList,pRandomElement,i)
{
if ((rOffset<=pRandomElement->rProb) && (lPreviousResChoosen!=i))
{
lElementChoosen=i;
uRes=pRandomElement->uRes;
bFound=TRUE;
break;
}
rOffset-=pRandomElement->rProb;
}
if (!bFound)
{/*if sum(prob)<1.0, choose the first element, or silence*/
if (lPreviousElementChoosen!=0)
{
lElementChoosen=0;
SNDLST2_M_StaticGetElementNumber(pRandomList,pRandomElement,0,i);
uRes=pRandomElement->uRes;
bFound=TRUE;
}
else
{
lElementChoosen=C_NOTHING_CHOOSEN;
uRes.pstPtr=SND_C_RES_FANTOME_PTR;
bFound=TRUE;
}
}
}
if (!bFound)
{/*no RANDOM element has been isolated (chosen); the "Nothing" element should be chosen (or there is a bug !)*/
lElementChoosen=C_NOTHING_CHOOSEN;
uRes.pstPtr=SND_C_RES_FANTOME_PTR;
}
res_random.pstPtr->uRes.stRandom.lLastElementChoosen=lElementChoosen;
if (lElementChoosen!=C_NOTHING_CHOOSEN)
res_random.pstPtr->uRes.stRandom.lLastResChoosen=lElementChoosen;
return uRes;
}
tduRefRes SND_fn_tdGetResourceChoosenRandom(tduRefRes res_random)
{
tdstRandomElement* pRandomElement;
int i;
if ((res_random.pstPtr->uRes.stRandom.lLastElementChoosen==C_NOTHING_CHOOSEN)
|| (res_random.pstPtr->uRes.stRandom.lLastElementChoosen>=SNDLST2_M_StaticGetNumberOfElements(&res_random.pstPtr->uRes.stRandom)))
/* nothing chosen*/
return SND_RES_FANTOME;
else
{
SNDLST2_M_StaticGetElementNumber(&res_random.pstPtr->uRes.stRandom
,pRandomElement
,res_random.pstPtr->uRes.stRandom.lLastElementChoosen
,i);
return pRandomElement->uRes;
}
}
/*
void SND_fn_vInitRandom(void)
{
}
void SND_fn_vDesInitRandom(void)
{
}
*/
long SND_fn_lPlayRandom(tduRefRes num_res,SoundParam* par,long prio,SND_td_pfn_vSoundCallback fn_callback,long par_callback)
{
tduRefRes low_res;
random_voice *pstRandomVoice;
SoundParam *pstSoundPar;
#ifdef NB_MICRO_MAX
SoundParam stSoundPar;
#endif
pstRandomVoice=SND_fn_pvMallocSndEx(E_ucSndBlockMain,sizeof(random_voice));
/*pstRandomVoice=SND_fn_pvMallocSnd(sizeof(random_voice));*/
pstRandomVoice->bValid=TRUE;
pstRandomVoice->uRes.pstPtr=num_res.pstPtr;
low_res=SND_fn_tdGetEffectiveResourceRandom(num_res);
if (low_res.pstPtr!=SND_C_RES_FANTOME_PTR)
{
#ifdef NB_MICRO_MAX
pstSoundPar=&stSoundPar;
#else
pstSoundPar=SND_fn_pCreateSoundParam(par->iNbLinks);
#endif
memcpy(pstSoundPar,par,SND_M_lGetSizeOfSoundParam(par));
/*sxd params are modified by Random static params*/
pstSoundPar->ucVol=(unsigned char)(((long)pstSoundPar->ucVol*pstRandomVoice->uRes.pstPtr->ucVolume)>>7);
pstSoundPar->iFlags|=C_SOUNDPARAM_COEF_VOL;
pstRandomVoice->lLowVoice=SND_fn_lPlaySnd(low_res,pstSoundPar,prio,fn_callback,par_callback,&pstRandomVoice->bValid);
#ifndef NB_MICRO_MAX
SND_fn_vDestroySoundParam(pstSoundPar);
#endif
if (pstRandomVoice->lLowVoice!=C_PLAY_FAILED)
return (long)pstRandomVoice;
}
/*failed*/
SND_fn_vFreeSndEx(E_ucSndBlockMain,pstRandomVoice);
/*SND_fn_vFreeSnd(pstRandomVoice);*/
return C_PLAY_FAILED;
}
SndBool SND_CALL SND_fn_bSetParamRandom(long voice,SoundParam* par)
{
SndBool bRet;
random_voice *pstRandomVoice=(random_voice*)voice;
SoundParam *pstSoundPar;
#ifdef NB_MICRO_MAX
SoundParam stSoundPar;
#endif
#ifdef NB_MICRO_MAX
pstSoundPar=&stSoundPar;
#else
pstSoundPar=SND_fn_pCreateSoundParam(par->iNbLinks);
#endif
memcpy(pstSoundPar,par,SND_M_lGetSizeOfSoundParam(par));
/*sxd params are modified by Random static params*/
pstSoundPar->ucVol=(unsigned char)(((long)pstSoundPar->ucVol*pstRandomVoice->uRes.pstPtr->ucVolume)>>7);
pstSoundPar->iFlags|=C_SOUNDPARAM_COEF_VOL;
if (pstRandomVoice->bValid && SND_fn_bSetParamSnd(pstRandomVoice->lLowVoice,pstSoundPar))
bRet=TRUE;
else
{
SND_fn_vFreeSndEx(E_ucSndBlockMain,pstRandomVoice);
/* SND_fn_vFreeSnd(pstRandomVoice);*/
bRet=FALSE;
}
return bRet;
}
SndBool SND_CALL SND_fn_bTestIsPlayingRandom(long voice)
{
random_voice *pstRandomVoice=(random_voice*)voice;
if (pstRandomVoice->bValid && SND_fn_bTestIsPlayingSnd(pstRandomVoice->lLowVoice))
return TRUE;
else
{
SND_fn_vFreeSndEx(E_ucSndBlockMain,pstRandomVoice);
/*SND_fn_vFreeSnd(pstRandomVoice);*/
return FALSE;
}
}
void SND_CALL SND_fn_vStopRandom(long voice)
{
random_voice *pstRandomVoice=(random_voice*)voice;
if (pstRandomVoice->bValid)
SND_fn_vStopSnd(pstRandomVoice->lLowVoice);
SND_fn_vFreeSndEx(E_ucSndBlockMain,pstRandomVoice);
/* SND_fn_vFreeSnd(pstRandomVoice);*/
}
void SND_CALL SND_fn_vPauseRandom(long voice)
{
random_voice *pstRandomVoice=(random_voice*)voice;
if (pstRandomVoice->bValid)
SND_fn_vPauseSnd(pstRandomVoice->lLowVoice);
}
void SND_CALL SND_fn_vResumeRandom(long voice)
{
random_voice *pstRandomVoice=(random_voice*)voice;
if (pstRandomVoice->bValid)
SND_fn_vResumeSnd(pstRandomVoice->lLowVoice);
}
void SND_fn_vRemoveCallbackRandom(long voice)
{
random_voice *pstRandomVoice=(random_voice*)voice;
if (pstRandomVoice->bValid)
SND_fn_vRemoveCallbackSnd(pstRandomVoice->lLowVoice);
}
void SND_fn_vUnLoadResRandom(tdstBlockResourceMem* mem)
{
}
SndReal SND_CALL SND_fn_rGetPosRandom(long voice)
{
random_voice *pstRandomVoice=(random_voice*)voice;
if (pstRandomVoice->bValid)
return SND_fn_rGetPosSnd(pstRandomVoice->lLowVoice);
else
return SND_C_POS_UNKNOWN;
}
SndReal SND_CALL SND_fn_rGetLengthRandom(long voice)
{
random_voice *pstRandomVoice=(random_voice*)voice;
if (pstRandomVoice->bValid)
return SND_fn_rGetLengthSnd(pstRandomVoice->lLowVoice);
else
return SND_C_LENGTH_UNKNOWN;
}
/*---- gestion des ressources de type RANDOM*/
void SND_fn_vConvertResDiskToMemRandom(tdstBlockResourceDisk* disk,tdstBlockResourceMem* mem,void* ptrBegin)
{
mem->Id=disk->Id;
mem->eType=disk->eType;
mem->eStorage=disk->eStorage;
mem->ucVolume=disk->ucVolume;
mem->bIsLoaded=TRUE;
/*partie specifique au type de ressource*/
mem->uRes.stRandom.ulNbElements = disk->uRes.stRandom.ulNbElements;
mem->uRes.stRandom.rProbNothing= disk->uRes.stRandom.rProbNothing;
mem->uRes.stRandom.bNothingCanBeChosenTwice= disk->uRes.stRandom.bNothingCanBeChosenTwice;
/*parametre dynamique*/
mem->uRes.stRandom.lLastElementChoosen=C_NEVER_CHOOSEN;
mem->uRes.stRandom.lLastResChoosen=C_NEVER_CHOOSEN;
}
#ifndef NO_ACP_SCRIPT
SndBool SND_fn_bLoadResScriptRandom(tdstBlockResourceDisk *disk,tdstBlockResourceMem *mem)
{
SND_fn_vConvertResDiskToMemRandom(disk,mem,NULL);
return TRUE;
}
#endif
#ifndef NO_ACP_LDBIN
SndBool SND_fn_bLoadResBinaryRandom(tdstBlockResourceDisk *_pBRDisk,tdstBlockResourceMem *_pBRMem,char *pDataBloc)
{
tdstRandomElement *pRandomArray,*pRandomElement;
int iPos;
/* Convert the ulDataOffset member to a pointer:*/
pRandomArray=(tdstRandomElement *)(pDataBloc + _pBRDisk->ulDataOffset);
/* Set pointers to range list:*/
SNDLST2_M_StaticSetMember(&_pBRMem->uRes.stRandom,hFirstElement,pRandomArray);
SNDLST2_M_StaticSetMember(&_pBRMem->uRes.stRandom, lNumberOfElements, _pBRDisk->uRes.stRandom.ulNbElements);
/* Reset pointers in range:*/
SNDLST2_M_StaticForEachElementOf( &_pBRMem->uRes.stRandom, pRandomElement, iPos)
{
pRandomElement->uRes.pstPtr=SND_fn_pGetBinRes(pRandomElement->uRes.Id);
}
SND_fn_vConvertResDiskToMemRandom(_pBRDisk,_pBRMem,NULL);
return TRUE;
}
#endif
/*get the final simple resource*/
tduRefRes SND_fn_tduGetLowestResourceRandom(tduRefRes uHighRes,SoundParam* par,SndBool eval)
{
tduRefRes uResRandom;
if (eval)
uResRandom=SND_fn_tdGetEffectiveResourceRandom(uHighRes);
else
uResRandom=SND_fn_tdGetResourceChoosenRandom(uHighRes);
return SND_fn_tduGetLowestResourceSnd(uResRandom,par,eval);
}
/*
//return combinaison of static volumes for RanDom/Switch resources
unsigned char SND_fn_ucGetStaticFinalVolumeRandom(tduRefRes uHighRes,SoundParam* par)
{
if (uHighRes.pstPtr==SND_C_RES_FANTOME_PTR) return C_SOUNDVOL_MAXI;
switch (uHighRes.pstPtr->eType)
{
case TYPE_SAMPLE:
case TYPE_MIDI:
case TYPE_CDAUDIO:
case TYPE_SEQUENCE:
case TYPE_THEME:
return C_SOUNDVOL_MAXI;
case TYPE_RANDOM:
return (unsigned char)(((long)uHighRes.pstPtr->ucVolume*(long)SND_fn_ucGetStaticFinalVolumeRandom(uHighRes,par))>>7);
case TYPE_SWITCH:
return (unsigned char)(((long)uHighRes.pstPtr->ucVolume*(long)SND_fn_ucGetStaticFinalVolumeSwitch(uHighRes,par))>>7);
case TYPE_SPLIT:
case TYPE_INVALID:
default:
SND_M_DisplayError(E_uwSndInvalidTypeOfResource,"");
return C_SOUNDVOL_MAXI;
}
}
*/
SndBool SND_CALL SND_fn_bSetResourceStaticVolumeRandom(tdstBlockResourceMem* pstRes,unsigned char ucVolume)
{
pstRes->ucVolume=ucVolume;
return TRUE;
}
#endif /*NO_ACP_SOUND*/