/*-------------------------------------------------------------------*/ /*! !*/ /*! 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*/