/*============================================================================================== * FILE "SNDADPCM.C" * * Created : 31 / 10 / 97 * Author : Stephane Ronse & Nicolas Meyer * Description: Code source file which manage ADPCM conversion * and play. Works with Dx3D, Dx2D, WinMM DLL. * Formalism : Public functions are prefixed with "SND_" * Ubi guidelines * * Copyright (C) 1997 by Ubi Sound Studio Entertainment * All rights Reserved *==============================================================================================*/ /* Super Public*/ #if 0 #include #endif #include "SNDinc.h" #include "sndres.h" #include "sndxd.h" #if defined(_DLL_COMPILATION_MODE) #include "snddll.h" #endif #ifndef DISABLE_ADPCM #ifndef NO_ACP_SOUND /* Moyen public*/ #include "Sndadpcm.h" #include "Sndthrd.h" #include "ApmThrd.h"/*En-tete contenant du code multi tâche*/ /* Prive*/ #include "Adpcm.h" #include "Adpcm.hxx" #include "Adpcm.cxx" /* DECLARATION DES FONCTIONS*/ /*==================================================*/ void SND_CALL fn_vRefreshSynchroneADPCM( long lIdBuffer, unsigned long ulStart, unsigned long ulSizeByte, void* pvBuffer ); void SND_CALL fn_vRefreshASynchroneADPCM( long lIdBuffer, unsigned long ulStart, unsigned long ulSizeByte, void* pvBuffer ); SndBool fn_bConvertBlockResDiskADPCMtoWAV(tdstBlockResourceDisk* pstDiskADPCM,void* ptrDataADPCM,tdstBlockResourceDisk* pstDiskWAV); SndBool fn_bConvertDataADPCMtoWAV(tdstBlockResourceDisk* pstDiskADPCM,void* ptrDataADPCM,void* ptrDataWAV); /*==================================================*/ /* * STRUCTURE DEFINITIONS */ typedef struct { long lBufferId; unsigned long ulSizeLast; unsigned long ulSizePos; } tdstBufferDescriptor; /* * GLOBALES VARIABLES */ static tdstBufferDescriptor gstASynch; static tdstBufferDescriptor gstSynch; static long gbDecompress; /* Mutex qui gere le multi-tâche*/ static SndBool gbClientPause; /* Flag qui indique que le buffer client est dejà en pause*/ static SndBool gbInitDone = FALSE; /* Flag qui indique l'init du module "ADPCM" c'est faite sans encombre*/ static SND_tdstADPCMCriticalSection gstSection; /* * Current file name & error information */ static char gchFileName[] = "SndAdpcm.c"; static char gchBuffer[256]; /* * DEFINITION DES FONCTIONS */ void SND_fn_vConvertResDiskToMemSampleADPCM( tdstBlockResourceDisk *disk, tdstBlockResourceMem *mem, void* ptrBegin ) { snd_assert(disk->eType==TYPE_SAMPLE); snd_assert( disk->uRes.stSample.eZip == SAMPLE_ADPCM ); 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.stSample.eZip = SAMPLE_ADPCM; mem->uRes.stSample.bPitchable = disk->uRes.stSample.bPitchable; mem->uRes.stSample.bVolable = disk->uRes.stSample.bVolable; mem->uRes.stSample.bPanable = disk->uRes.stSample.bPanable; mem->uRes.stSample.bSpacable = disk->uRes.stSample.bSpacable; mem->uRes.stSample.bReverbable = disk->uRes.stSample.bReverbable; mem->uRes.stSample.bStream = disk->uRes.stSample.bStream; mem->uRes.stSample.bLoop = disk->uRes.stSample.bLoop; mem->uRes.stSample.ulFreq = disk->uRes.stSample.ulFreq; mem->uRes.stSample.uwResolution = disk->uRes.stSample.uwResolution; mem->uRes.stSample.uwNbChannels = disk->uRes.stSample.uwNbChannels; if( disk->uRes.stSample.bStream ) { /*sample streame*/ strcpy( mem->uRes.stSample.uData.stStream.szFileName, disk->uRes.stSample.czFileName ); mem->uRes.stSample.uData.stStream.ulOffsetFirst = disk->ulDataOffset; if( ! disk->uRes.stSample.bLoop ) { mem->uRes.stSample.uData.stStream.ulOffsetLoop = 0; /* Indice de sample*/ mem->uRes.stSample.uData.stStream.ulOffsetLast = disk->ulDataOffset+disk->ulDataSize; /* Nombre de samples*/ } else { mem->uRes.stSample.uData.stStream.ulOffsetLoop = disk->ulDataOffset+disk->uRes.stSample.ulStartLoop; mem->uRes.stSample.uData.stStream.ulOffsetLast = disk->ulDataOffset+disk->uRes.stSample.ulStartLoop+disk->uRes.stSample.ulLoopLength; } } else {/*sample non streame*/ mem->uRes.stSample.uData.stMem.ulNbEchLoop = disk->uRes.stSample.ulStartLoop; mem->uRes.stSample.uData.stMem.ulNbEch = disk->uRes.stSample.ulLoopLength; mem->uRes.stSample.uData.stMem.pvPtrFirst = ptrBegin; snd_assert( ! ( (unsigned long)mem->uRes.stSample.uData.stMem.pvPtrFirst % 4 ) ); } /*le sample est pret à l'emplois*/ } char gchNoVoice[] = "No active voice."; char gchInvalPa[] = "Address non affected."; char gchNoTheme[] = "None possibility to play theme."; char gchNotAdpm[] = "Is not ADPCM datas."; char gchBadForm[] = "Bad format."; long SND_fn_lPlaySampleADPCM( tduRefRes res, SampleParam *par, long prio, SND_td_pfn_vSoundCallback fn_callback, long par_callback ) { long lId; char* pchString; if( gbInitDone ) { SND_fn_vEnterCriticalSection( & gstSection ); switch( fn_ulAddVoiceADPCM( res.pstPtr , par , fn_callback , par_callback , NULL , & lId , gstSynch.ulSizePos ) ) { /* L'allocation de la voie a ete faite*/ case ADPCM_NOERROR: break; case ADPCM_NOVOICELEFT: pchString = gchNoVoice; lId = C_PLAY_FAILED; break; case ADPCM_INVALIDPARAM: pchString = gchInvalPa; lId = C_PLAY_FAILED; break; case ADPCM_NOTHEMELEFT: pchString = gchNoTheme; lId = C_PLAY_FAILED; break; case ADPCM_NOTADPCMDATAS: pchString = gchNotAdpm; lId = C_PLAY_FAILED; break; default: pchString = gchBadForm; lId = C_PLAY_FAILED; } SND_fn_vLeaveCriticalSection( & gstSection ); if( lId == C_PLAY_FAILED ) SND_fn_vDisplayError( E_uwSndSystemError, pchString ); } return lId; } void SND_fn_vRemoveCallbackSampleADPCM( long voice ) { if( gbInitDone ) { SND_fn_vEnterCriticalSection( & gstSection );/* Entree en section critique*/ fn_ulRemoveVoiceCallbackADPCM( voice ); SND_fn_vLeaveCriticalSection( & gstSection );/* Sortie de section critique*/ } } SndBool SND_fn_bSetParamSampleADPCM( long voice, SampleParam *par ) { SndBool bRet = FALSE; if( gbInitDone ) { SND_fn_vEnterCriticalSection( & gstSection );/* Entree en section critique*/ if( fn_ulSetParams( voice, par ) == ADPCM_NOERROR ) { bRet = TRUE; } SND_fn_vLeaveCriticalSection( & gstSection );/* Sortie de section critique*/ } return bRet; } SndBool SND_fn_bTestIsPlayingSampleADPCM( long voice ) { if( gbInitDone ) { if( fn_bVoiceIsPlayingADPCM( voice ) ) return TRUE; } return FALSE; } void SND_fn_vStopSampleADPCM( long voice ) { if( gbInitDone ) { if( voice ) { SND_fn_vEnterCriticalSection( & gstSection ); fn_ulRemoveVoiceADPCM( voice ); SND_fn_vLeaveCriticalSection( & gstSection ); } } } void SND_fn_vPauseSampleADPCM( long voice ) { if( gbInitDone ) { SND_fn_vEnterCriticalSection( & gstSection ); fn_ulPauseVoiceADPCM( voice ); SND_fn_vLeaveCriticalSection( & gstSection ); } } void SND_fn_vResumeSampleADPCM(long voice) { if( gbInitDone ) { SND_fn_vEnterCriticalSection( & gstSection ); fn_ulResumeVoiceADPCM( voice ); SND_fn_vLeaveCriticalSection( & gstSection ); } } SndBool SND_fn_bIsResourceLoopingSampleADPCM(tduRefRes res) { return res.pstPtr->uRes.stSample.bLoop; } SndReal SND_fn_rGetPosSampleADPCM( long voice ) { SndReal rAnswer; rAnswer = SND_C_LENGTH_UNKNOWN; if( gbInitDone ) { double dTime; switch( fn_ulGetPosVoiceADPCM( voice, &dTime, gstASynch.ulSizePos ) ) { case ADPCM_NOERROR: rAnswer = M_DoubleToRealSnd( dTime ); /* Retourne un reel 16 16*/ break; case ADPCM_ENDREACH: rAnswer = SND_C_POS_ENDED; break; } } return rAnswer; } SndReal SND_fn_rGetLengthSampleADPCM(long voice) { SndReal rAnswer; rAnswer = SND_C_LENGTH_UNKNOWN; if( gbInitDone ) { unsigned long ulLength; if( fn_ulGetLengthVoiceADPCM( voice, & ulLength ) == ADPCM_NOERROR ) { double dTemp; /* La valeur à retourner est en seconde. ( SND_ADPCM_BUFFERFREQ samples font 1s )*/ dTemp = (double)ulLength / (double)SND_ADPCM_BUFFERFREQ; rAnswer = M_DoubleToRealSnd( dTemp ); /* Retourne un reel 16 16*/ /* return ulLength << 16; // Retourne un reel 16 16*/ } } return rAnswer; } /*************************************************************************/ /* FONCTIONS INUTILES*/ void SND_fn_vSetSoundVolumeSampleADPCM(unsigned char vol) { } unsigned char SND_fn_ucGetSoundVolumeSampleADPCM() { return 0; } void SND_fn_vSetStereoSampleADPCM(SndBool active) { } SndBool SND_fn_bGetStereoSampleADPCM(void) { return TRUE; } void SND_fn_vSetReverseStereoSampleADPCM(SndBool active) { fn_vSetReverseStereoSampleADPCM(active); } SndBool SND_fn_bGetReverseStereoSampleADPCM(void) { return fn_bGetReverseStereoSampleADPCM(); } /* fin FONCTIONS INUTILES*/ /****************************************************************************/ int SND_fn_iInitSampleADPCM( SND_tdstInitStruct *pInitStruct ) { unsigned long ulAnswer; SND_tdstFormat stFormatClient; SND_tdstCallback stCallback; ulAnswer = C_INIT_FAILED; if( fn_ulInitModuleADPCM( ) == ADPCM_NOERROR ) { /* * Client buffer for "One Shot Voices" */ stFormatClient.eZip = SAMPLE_PCM; stFormatClient.uFormat.stPCM.ulNbSamples = 0; stFormatClient.uFormat.stPCM.uwResolution = 16; stFormatClient.uFormat.stPCM.uwNbChannels = 2; stFormatClient.uFormat.stPCM.ulFreq = SND_ADPCM_BUFFERFREQ; memset( & stCallback, 0, sizeof(SND_tdstCallback) ); stCallback.eType = BUFFER_SYNCHRONE; stCallback.uCallback.CallbackASynchrone = fn_vRefreshSynchroneADPCM; gstSynch.lBufferId = SND_fn_lCreateNewBufferExSxd( & stFormatClient, &stCallback, NULL, 0 ); if( gstSynch.lBufferId != C_PLAY_FAILED ) { /* * Client buffer for "Streaming Voices" */ stFormatClient.uFormat.stPCM.ulNbSamples = M_SIZE_ASSYNCHRONE; stCallback.eType = BUFFER_ASYNCHRONE; stCallback.uCallback.CallbackASynchrone = fn_vRefreshASynchroneADPCM; stCallback.uInfo.rCallbackPeriod = 0; gstASynch.lBufferId = SND_fn_lCreateNewBufferExSxd( & stFormatClient, &stCallback, NULL, 0 ); if( gstASynch.lBufferId != C_PLAY_FAILED ) { SND_fn_vInitializeCriticalSection( & gstSection );/* Creation d'une section critique */ gbClientPause = FALSE; gbInitDone = TRUE; ulAnswer = C_INIT_OK; } else SND_fn_vDeleteBufferSxd( gstSynch.lBufferId ); } /* Client Buffer cannot be created when SoundDriver is busy -> no assert please snd_assert( gstSynch.lBufferId != C_PLAY_FAILED ); snd_assert( gstASynch.lBufferId != C_PLAY_FAILED ); */ } return ulAnswer; } SndBool SND_fn_bTestInitSampleADPCM( void ) { return TRUE; } void SND_fn_vDesInitSampleADPCM( void ) { if( gbInitDone ) { SND_fn_vDeleteBufferSxd( gstSynch.lBufferId ); SND_fn_vDeleteBufferSxd( gstASynch.lBufferId ); SND_fn_vDeleteCriticalSection( & gstSection );/* Destruction d'une section critique */ } } void SND_fn_vSetEffectSampleADPCM(long num) { } void SND_fn_vCreateMicroSampleADPCM(MicroParam* par,long id) { } void SND_fn_vSetMicroParamSampleADPCM(long sxdId,MicroParam* par) { } void SND_fn_vDestroyMicroSampleADPCM(long sxdId) { } /*gestion de buffers A VOIR*/ long SND_fn_lCreateNewBufferSampleADPCM(unsigned long nb_samples,unsigned short uwResolution,unsigned short uwNbChannels,unsigned long ulFreq,SampleParam* par,td_pfn_vRefreshBufferClient callback,long user_id) { return C_PLAY_FAILED; } void SND_fn_vSetParamBufferSampleADPCM(long id_buffer,SampleParam *par) { } void SND_fn_vDeleteBufferSampleADPCM(long id_buffer) { } void SND_fn_vPauseBufferSampleADPCM( long id_buffer ) { if( gbInitDone ) { if( ! gbClientPause ) { SND_fn_vPauseBufferSxd( gstSynch.lBufferId ); SND_fn_vPauseBufferSxd( gstASynch.lBufferId ); gbClientPause = TRUE; } } } void SND_fn_vResumeBufferSampleADPCM( long id_buffer ) { if( gbInitDone ) { if( gbClientPause ) { SND_fn_vResumeBufferSxd( gstSynch.lBufferId ); SND_fn_vResumeBufferSxd( gstASynch.lBufferId ); gbClientPause = FALSE; } } } /* OBSOLETE*/ void* SND_fn_pvGetPtrBufferSampleADPCM(long id_buffer) { return NULL; } SndReal SND_fn_rGetPosBufferSampleADPCM(long id_buffer) { return SND_C_POS_UNKNOWN; } #if !defined(NO_ACP_SCRIPT) || defined(_DLL_COMPILATION_MODE) /*this function must be defined in Script/Hybrid or DLL mode*/ SndBool SND_fn_bLoadResScriptSampleADPCM( tdstBlockResourceDisk *disk, tdstBlockResourceMem *mem ) { SndBool bAnswer; void* pvData; char file_name[ 256 ]; bAnswer = FALSE; if( gbInitDone ) { if( !disk->uRes.stSample.bStream ) { pvData = SND_fn_pvMallocSnd( disk->ulDataSize ); if( pvData ) { /* Le "ResolveFileName" est tres important ici*/ SND_fn_vResolveFileName( disk->uRes.stSample.czFileName, file_name ); if ( !SND_fn_bLoadDataInMem( pvData, disk->ulDataSize, file_name, disk->ulDataOffset ) ) { sprintf( gchBuffer, "Src %s\nData %s\nDisk %x", gchFileName, disk->uRes.stSample.czFileName, disk ); SND_fn_vDisplayError( E_uwSndErrorReadingFile, gchBuffer ); SND_fn_vFreeSnd( pvData ); pvData = NULL; } else bAnswer = TRUE; } } else { bAnswer = TRUE; pvData = NULL; } if( bAnswer ) { /* * en script, chaque ressources charge ces propres data (on ne tient pas compte de eStorage) */ SND_fn_vConvertResDiskToMemSampleADPCM( disk, mem, pvData ); mem->eStorage=TYPE_EXTERNAL; } } return bAnswer; } #endif SndBool SND_fn_bLoadResBinarySampleADPCM(tdstBlockResourceDisk *disk,tdstBlockResourceMem *mem,char *pDataBloc) { void* pData; char file_name[ 256 ]; if (!gbInitDone) return FALSE; if (!disk->uRes.stSample.bStream) { /* Sample is not streaming: must be really loaded in memory*/ if (disk->eStorage!=TYPE_EXTERNAL) { /* Sample is in the bank: its position is known relatively to pDataBloc:*/ pData=(void *)(pDataBloc +disk->ulDataOffset); } else { /* Sample is external: it must be loaded from a file:*/ pData=SND_fn_pvMallocSnd(disk->ulDataSize); SND_fn_vResolveFileName(disk->uRes.stSample.czFileName,file_name); if (!SND_fn_bLoadDataInMem(pData,disk->ulDataSize,file_name,disk->ulDataOffset)) { sprintf( gchBuffer, "Src %s\nData %s\nDisk %x", gchFileName, disk->uRes.stSample.czFileName, disk ); SND_fn_vDisplayError( E_uwSndErrorReadingFile, gchBuffer ); SND_fn_vFreeSnd(pData); pData=NULL; } } } else pData=NULL; /* Sample is streaming*/ SND_fn_vConvertResDiskToMemSampleADPCM( disk, mem, pData ); return TRUE; } #if !defined(NO_ACP_SCRIPT) || defined(_DLL_COMPILATION_MODE) /*this function must be defined in Script/Hybrid or DLL mode*/ /*conversion d'un BlockResDisk ADPCM en BlockResMem WAV pour les non streames*/ SndBool SND_fn_bLoadResScriptAndConvertToWAVSampleADPCM( tdstBlockResourceDisk *disk, tdstBlockResourceMem *mem ) { void *pDataWAV,*pDataADPCM; tdstBlockResourceDisk stPseudoRes; char file_name[ 256 ]; if (!gbInitDone) return FALSE; if( ! disk->uRes.stSample.bStream ) { /*chargement de l'ADPCM*/ pDataADPCM = SND_fn_pvMallocSnd( disk->ulDataSize ); if( pDataADPCM == NULL ) return FALSE; /* Le "ResolveFileName" est tres important ici*/ SND_fn_vResolveFileName( disk->uRes.stSample.czFileName, file_name ); if ( ! SND_fn_bLoadDataInMem( pDataADPCM, disk->ulDataSize, file_name, disk->ulDataOffset ) ) { sprintf( gchBuffer, "Src %s\nData %s\nDisk %x", gchFileName, disk->uRes.stSample.czFileName, disk ); SND_fn_vDisplayError( E_uwSndErrorReadingFile, gchBuffer ); SND_fn_vFreeSnd( pDataADPCM ); return FALSE; } memcpy(&stPseudoRes,disk,sizeof(stPseudoRes)); /*conversion du BlockResDisk*/ if (!fn_bConvertBlockResDiskADPCMtoWAV(disk,pDataADPCM,&stPseudoRes)) { sprintf( gchBuffer, "Src %s\nData %s\nDisk %x\nConvertion block res failed", gchFileName, disk->uRes.stSample.czFileName, disk ); SND_fn_vDisplayError( E_uwSndErrorReadingFile, gchBuffer ); SND_fn_vFreeSnd( pDataADPCM ); return FALSE; } /*malloc pour les data WAV*/ pDataWAV=SND_fn_pvMallocSnd(stPseudoRes.ulDataSize); /*conversion des data*/ if (!fn_bConvertDataADPCMtoWAV(disk,pDataADPCM,pDataWAV)) { sprintf( gchBuffer, "Src %s\nData %s\nDisk %x\nConvertion data failed", gchFileName, disk->uRes.stSample.czFileName, disk ); SND_fn_vDisplayError( E_uwSndErrorReadingFile, gchBuffer ); SND_fn_vFreeSnd( pDataADPCM ); SND_fn_vFreeSnd( pDataWAV ); return FALSE; } if (disk->eStorage==TYPE_EXTERNAL) SND_fn_vFreeSnd( pDataADPCM ); /*generation du BlockResMem*/ SND_fn_vConvertResDiskToMemSxd( &stPseudoRes, mem, pDataWAV ); /*en script, chaque ressources charge ces propres data (on ne tient pas compte de eStorage)*/ mem->eStorage=TYPE_EXTERNAL; return TRUE; } else { /*stream sample are not converted to WAV, but played in APDMC*/ return SND_fn_bLoadResScriptSampleADPCM(disk,mem); } } #endif /*conversion d'un BlockResDisk ADPCM en BlockResMem WAV pour les non streames*/ SndBool SND_fn_bLoadResBinaryAndConvertToWAVSampleADPCM(tdstBlockResourceDisk *disk,tdstBlockResourceMem *mem,char *pDataBloc) { void *pDataWAV,*pDataADPCM; tdstBlockResourceDisk stPseudoRes; char file_name[ 256 ]; if (!gbInitDone) return FALSE; /* * Sample is not streaming: must be really loaded in memory */ if( !disk->uRes.stSample.bStream ) { if (disk->eStorage!=TYPE_EXTERNAL) { /* Sample is in the bank: its position is known relatively to pDataBloc:*/ pDataADPCM=(void *)(pDataBloc +disk->ulDataOffset); } else { /* Sample is external: it must be loaded from a file:*/ pDataADPCM=SND_fn_pvMallocSnd(disk->ulDataSize); SND_fn_vResolveFileName(disk->uRes.stSample.czFileName,file_name); if (!SND_fn_bLoadDataInMem(pDataADPCM,disk->ulDataSize,file_name,disk->ulDataOffset)) { sprintf( gchBuffer, "Src %s\nData %s\nDisk %x\nConvertion data failed", gchFileName, disk->uRes.stSample.czFileName, disk ); SND_fn_vDisplayError( E_uwSndErrorReadingFile, gchBuffer ); SND_fn_vFreeSnd(pDataADPCM); return FALSE; } } memcpy(&stPseudoRes,disk,sizeof(stPseudoRes)); /*conversion du BlockResDisk*/ if( !fn_bConvertBlockResDiskADPCMtoWAV(disk,pDataADPCM,&stPseudoRes)) { // snd_assert( 0 ); sprintf( gchBuffer, "Src %s\nData %s\nDisk %x\nConvertion block failed", gchFileName, disk->uRes.stSample.czFileName, disk ); SND_fn_vDisplayError( E_uwSndErrorReadingFile, gchBuffer ); SND_fn_vFreeSnd( pDataADPCM ); return FALSE; } /*malloc pour les data WAV*/ pDataWAV=SND_fn_pvMallocSnd(stPseudoRes.ulDataSize); /*conversion des data*/ if (!fn_bConvertDataADPCMtoWAV(disk,pDataADPCM,pDataWAV)) { snd_assert( 0 ); SND_fn_vDisplayError( E_uwSndInvalidTypeOfResource, "Cannot convert ADPCM resource"); SND_fn_vFreeSnd( pDataADPCM ); SND_fn_vFreeSnd( pDataWAV ); return FALSE; } if (disk->eStorage==TYPE_EXTERNAL) SND_fn_vFreeSnd( pDataADPCM ); /*generation du BlockResMem*/ SND_fn_vConvertResDiskToMemSxd( &stPseudoRes, mem, pDataWAV ); /*en script, chaque ressources charge ces propres data (on ne tient pas compte de eStorage)*/ mem->eStorage=TYPE_EXTERNAL; return TRUE; } else { return SND_fn_bLoadResBinarySampleADPCM(disk,mem,pDataBloc); } } void SND_fn_vUnLoadResSampleADPCM( tdstBlockResourceMem* mem ) { if( !mem->uRes.stSample.bStream ) { if( ( mem->uRes.stSample.uData.stMem.pvPtrFirst != NULL ) && ( mem->eStorage == TYPE_EXTERNAL ) ) SND_fn_vFreeSnd( mem->uRes.stSample.uData.stMem.pvPtrFirst ); } mem->uRes.stSample.uData.stMem.pvPtrFirst = NULL; mem->eType = TYPE_INVALID; } SndBool SND_fn_bIsResLoadedSampleADPCM( tdstBlockResourceMem *mem ) { return FALSE; } /*---themes*/ long SND_fn_lPlayTransitionSampleADPCM( tduRefRes FirstRes, tduRefRes NextRes, SND_td_pfn_vSoundCallback transition_callback, long param_callback, SampleParam* par ) { long lId = C_PLAY_FAILED; snd_assert(FirstRes.pstPtr->uRes.stSample.eZip==SAMPLE_ADPCM);snd_assert(NextRes.pstPtr->uRes.stSample.eZip==SAMPLE_ADPCM); if( gbInitDone ) { SND_fn_vEnterCriticalSection( & gstSection );/* Entree en section critique*/ if( fn_ulAddVoiceADPCM( FirstRes.pstPtr , par , transition_callback , param_callback , NextRes.pstPtr , & lId , gstSynch.ulSizePos ) != ADPCM_NOERROR ) lId = C_PLAY_FAILED; SND_fn_vLeaveCriticalSection( & gstSection );/* Sortie de section critique*/ } return lId; } SndBool SND_fn_bSetParamTransitionSampleADPCM( long voice, SampleParam *par ) { SndBool bRet=FALSE; if( gbInitDone ) { if( voice ) { SND_fn_vEnterCriticalSection( & gstSection ); if( fn_ulSetParams( voice, par ) == ADPCM_NOERROR ) bRet=TRUE; else bRet=FALSE; SND_fn_vLeaveCriticalSection( & gstSection ); } } return bRet; } SndBool SND_fn_bSetNextTransitionSampleADPCM( long voice, tduRefRes new_res ) { SndBool bRet = FALSE; if( gbInitDone ) { SND_fn_vEnterCriticalSection( & gstSection );/* Entree en section critique*/ if( fn_ulSetNextThemeADPCM( voice, new_res.pstPtr ) == ADPCM_NOERROR ) bRet = TRUE; SND_fn_vLeaveCriticalSection( & gstSection );/* Sortie de section critique*/ } return bRet; } /* SEUL CAS OU ARRETE UNE PART EN COURS*/ SndBool SND_fn_bDoTransitionWithFadeSampleADPCM( long voice, tduRefRes new_res, SndReal rDuration ) { SndBool bRet = FALSE; if( gbInitDone ) { SND_fn_vEnterCriticalSection( & gstSection );/* Entree en section critique*/ bRet = fn_bFadeThemeADPCM( voice, new_res.pstPtr, rDuration ); SND_fn_vLeaveCriticalSection( & gstSection );/* Sortie de section critique*/ } return bRet; } void SND_fn_vStopTransitionSampleADPCM( long voice ) { if( gbInitDone ) { SND_fn_vEnterCriticalSection( & gstSection ); fn_vStopThemeADPCM( voice ); SND_fn_vLeaveCriticalSection( & gstSection ); } } void SND_fn_vPauseTransitionSampleADPCM( long voice ) { if( gbInitDone ) { SND_fn_vEnterCriticalSection( & gstSection ); fn_ulPauseVoiceADPCM( voice ); SND_fn_vLeaveCriticalSection( & gstSection ); } } void SND_fn_vResumeTransitionSampleADPCM( long voice ) { if( gbInitDone ) { SND_fn_vEnterCriticalSection( & gstSection ); fn_ulResumeVoiceADPCM( voice ); SND_fn_vLeaveCriticalSection( & gstSection ); } } #ifndef NO_ACP_LDBIN SndBool SND_fn_bCanFreeDataSampleADPCM(void) { return FALSE; } #endif /*--relache-reprise a chaud des drives*/ void SND_fn_vReleaseDriverSampleADPCM(void) { } void SND_fn_vRestoreDriverSampleADPCM(void) { } void SND_fn_vGetTargetLabelSampleADPCM(char* name,int nb_char) { } void SND_fn_vSetupTargetSampleADPCM() { } SndBool SND_fn_bCanSetupTargetSampleADPCM() { return FALSE; } void SND_fn_vSynchroSampleADPCM() { } long SND_fn_lCreateNewBufferExSampleADPCM(SND_tdstFormat* pformat,SND_tdstCallback* pCallback,SoundParam* par,long user_id) { return C_PLAY_FAILED; } long SND_fn_lGetPosBufferExSampleADPCM(long id_buffer) { return SND_C_POS_UNKNOWN; } long SND_fn_lPushBufferExSampleADPCM( long id_buffer, SND_tdstStackBuffer* pStack ) { return C_PLAY_FAILED; } #endif /*NO_ACP_SOUND*/ //#define M_SAVE_MIX_APM void SND_CALL fn_vRefreshSynchroneADPCM( long lIdBuffer, unsigned long ulStart, unsigned long ulSizeByte, void* pvBuffer ) { /* Play only memory resource */ static SndBool bRun = FALSE; unsigned long uMixerState; #ifdef M_SAVE_MIX_APM HANDLE hBinFile; DWORD dwWrite; #endif /* Protege reentrance*/ if( gbInitDone ) { if( ! bRun ) { bRun = TRUE; SND_fn_vEnterCriticalSection( & gstSection ); gbDecompress = TRUE; uMixerState = fn_ulMixerStereoADPCM( FALSE, ulSizeByte, (short*)pvBuffer, gstSynch.ulSizePos ); gstSynch.ulSizeLast = ulSizeByte; gstSynch.ulSizePos += ulSizeByte; #ifdef M_SAVE_MIX_APM hBinFile = CreateFile( "c:\\binapm.raw", GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_ALWAYS, 0, NULL ); SetFilePointer( hBinFile, 0, NULL, FILE_END ); WriteFile( hBinFile, pvBuffer, ulSizeByte << 2, &dwWrite, NULL ); CloseHandle( hBinFile ); #endif if( ( uMixerState == ADPCM_NOVOICELEFT ) || ( uMixerState == ADPCM_NOVOICEACTIVE ) ) memset( pvBuffer, 0, ulSizeByte << 2 ); gbDecompress = FALSE; SND_fn_vLeaveCriticalSection( & gstSection ); bRun = FALSE; } } } //#define M_SAVE_MIX_STRM_APM void SND_CALL fn_vRefreshASynchroneADPCM( long lIdBuffer, unsigned long ulStart, unsigned long ulSizeByte, void* pvBuffer ) { if( gbInitDone ) { static SndBool bRun; /* Play only streamed resource */ unsigned long uMixerState; #ifdef M_SAVE_MIX_STRM_APM HANDLE hBinFile; DWORD dwWrite; #endif /* * Protege reentrance */ bRun = FALSE; if( ! bRun ) { bRun = TRUE; SND_fn_vEnterCriticalSection( &gstSection ); /* * Actualize Asynchronous buffer envirronement */ gbDecompress = TRUE; uMixerState = fn_ulMixerStereoADPCM( TRUE, ulSizeByte, (short*)pvBuffer, gstASynch.ulSizePos ); /* * Store addition of all bytes refresh size */ gstASynch.ulSizeLast = ulSizeByte; gstASynch.ulSizePos += ulSizeByte; #ifdef M_SAVE_MIX_STRM_APM hBinFile = CreateFile( "c:\\binapmstr.raw", GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_ALWAYS, 0, NULL ); SetFilePointer( hBinFile, 0, NULL, FILE_END ); WriteFile( hBinFile, pvBuffer, ulSizeByte << 2, &dwWrite, NULL ); CloseHandle( hBinFile ); #endif if( ( uMixerState == ADPCM_NOVOICELEFT ) || ( uMixerState == ADPCM_NOVOICEACTIVE ) ) memset( pvBuffer, 0, ulSizeByte << 2 ); gbDecompress = FALSE; SND_fn_vLeaveCriticalSection( & gstSection ); bRun = FALSE; } } } SndBool SND_fn_bCheckVersionResourceSampleADPCM( tdstBlockResourceDisk* disk ) { SndBool bResult = FALSE; void* data; char file_name[ 256 ]; data = SND_fn_pvMallocSnd( disk->ulDataSize ); /* Le "ResolveFileName" est tres important ici*/ SND_fn_vResolveFileName( disk->uRes.stSample.czFileName, file_name ); if ( ! SND_fn_bLoadDataInMem( data, disk->ulDataSize, file_name, disk->ulDataOffset ) ) { SND_fn_vDisplayError( E_uwSndErrorReadingFile, gchFileName ); SND_fn_vFreeSnd( data ); data = NULL; } else { if( fn_ulResolveVersion( ( (lpSND_tdstWAVEFORMATEX)data )->ulCompressId ) == ADPCM_NOERROR ) bResult = TRUE; SND_fn_vFreeSnd( data ); } return bResult; } /*------------------------------------------------------*/ /* SND_fn_lGetNbVoiceWishedSampleADPCM: returns the maximum number of voices to be played in the same time*/ /*------------------------------------------------------*/ long SND_fn_lGetNbVoiceWishedSampleADPCM() { return 0x10; } /*!!!!!!!!!!!!!!!!!!fonctions de conversion ADPCM->WAV au chargement!!!!!!!!!!!!!!!!!!!!!!*/ /*---------------------------------------------------------*/ /* fn_bConvertBlockResDiskADPCMtoWAV: */ /* generation du BlockResDisk de la ressources WAV equivalente à une ressources ADPCM*/ /*Entrees:*/ /* pstDiskADPCM:descripteur de la ressources ADPCM (ne pas exploiter le FileName)*/ /* ptrDataADPCM:pointeur sur les data ADPMC dejà chargees*/ /* pstDiskWAV:descripteur de la ressources WAV à generer (un memcpy a dejà eu lieu)*/ /*Sortie:TRUE si OK, FALSE si echec (annulation de la conversion)*/ /*------------------------------------------------------------*/ SndBool fn_bConvertBlockResDiskADPCMtoWAV( tdstBlockResourceDisk* pstDiskADPCM, void* ptrDataADPCM, tdstBlockResourceDisk* pstDiskWAV ) { SndBool bAnswer; bAnswer = FALSE; memcpy( pstDiskWAV, pstDiskADPCM, sizeof(tdstBlockResourceDisk) ); /* * Modification de quelques champs */ pstDiskWAV->eType = TYPE_SAMPLE; pstDiskWAV->eStorage = 0; pstDiskWAV->ulDataOffset = 0; pstDiskWAV->uRes.stSample.eZip = SAMPLE_PCM; pstDiskWAV->uRes.stSample.czFileName[ 0 ] = 0; pstDiskWAV->uRes.stSample.bStream = FALSE; if( fn_ulFillSizeAndLoopADPCM( pstDiskWAV, ptrDataADPCM ) == ADPCM_NOERROR ) bAnswer = TRUE; return bAnswer; } /*-------------------------------------------------------------------*/ /* fn_bConvertDataADPCMtoWAV:*/ /* generation en memoire des data WAV correspondantes à une ressource ADPCM*/ /*Entrees:*/ /* pstDiskWAV:descripteur de la ressource WAV à conevrtir*/ /* ptrDataADPCM:pointeur sur les data ADPCM dejà chargees en memoire*/ /* ptrDataWAV:pointeur cible des donnees à generer*/ /*Retour:TRUE si OK, FALSE si echec (annulation de la conversion)*/ /*------------------------------------------------------------*/ SndBool fn_bConvertDataADPCMtoWAV( tdstBlockResourceDisk* pstDiskADPCM, void* ptrDataADPCM, void* ptrDataWAV ) { SndBool bAnswer; bAnswer = FALSE; if( fn_ulConvertDataADPCM( ptrDataADPCM, ptrDataWAV ) == ADPCM_NOERROR ) bAnswer = TRUE; return bAnswer; } SndBool SND_fn_bSetResourceStaticVolumeSampleADPCM(tdstBlockResourceMem* pstRes,unsigned char ucVolume) { int i; pstRes->ucVolume=ucVolume; for (i=0;i