reman3/Rayman_X/cpa/tempgrp/SND/src/sndadpcm.c

988 lines
30 KiB
C

/*==============================================================================================
* 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 <crtdbg.h>
#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<NB_MAX_ADPCM_VOICE;i++)
if (gstVoice[i].uRefRes.pstPtr!=NULL)
if (gstVoice[i].uRefRes.pstPtr==pstRes)
gstVoice[i].ulStaticVolume=ucVolume;
for (i=0;i<NB_MAX_ADPCM_THEME;i++)
if (gstTheme[i].uRefRes.pstPtr!=NULL)
if (gstTheme[i].uRefRes.pstPtr==pstRes)
gstTheme[i].ulStaticVolume=ucVolume;
if (gstVoiceFade.uRefRes.pstPtr!=NULL)
if (gstVoiceFade.uRefRes.pstPtr==pstRes)
gstVoiceFade.ulStaticVolume=ucVolume;
return TRUE;
}
#endif
/*
* DISABLE_ADPCM
*/