403 lines
12 KiB
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*/
|