1036 lines
31 KiB
C
1036 lines
31 KiB
C
/******************************************************************
|
|
CPA-SND : Sound module
|
|
MPEG ressources
|
|
******************************************************************/
|
|
|
|
#include "SNDinc.h"
|
|
|
|
#include "sndres.h"
|
|
|
|
#include "sndmpeg.h"
|
|
|
|
#if defined(_DLL_COMPILATION_MODE)
|
|
#include "snddll.h"
|
|
#else
|
|
#include "sndxd.h"
|
|
#endif
|
|
|
|
#ifndef DISABLE_MPEG
|
|
#include "mpeg.hxx"
|
|
#include <process.h>
|
|
#endif /*DISABLE_MPEG*/
|
|
|
|
#ifndef DISABLE_MPEG
|
|
extern unsigned char ucVolume[128];
|
|
static unsigned long ulIdBufferClient;
|
|
extern SndBool bInMPEGDecomp;
|
|
static SndBool bIsClientPaused;
|
|
static SndBool bIsMPEGReleased;
|
|
static SndBool bIsMPEGOk=FALSE;
|
|
|
|
extern SND_tdstMPEGVoice MPEGvoices[(kNumVoice+1)*2];
|
|
extern SND_tdstMPEGVoice *pSwapVoice[2]; /* Pointeur sur les deux fichiers MPEG à décoder pour un thème*/
|
|
tdstBlockResourceMem* MPEGCurrentRes[(kNumVoice+1)*2];
|
|
|
|
#define M_SND_MPEG_BUFFERFREQ 44100
|
|
/*
|
|
* FADE OF 10 SECONDS EXPRESSED IN SNDREAL
|
|
*/
|
|
#define M_FADE_DURATION_MPEG M_IntToRealSnd( 4 )
|
|
|
|
|
|
/*thread lancée à chaque occurence de callback*/
|
|
/*int WINAPI start_callback_thread(DWORD *param)*/
|
|
#if defined(__WATCOMC__) && (__WATCOMC__<1100)
|
|
void start_callback_threadMPEG(callback_paramMPEG *callback_par)
|
|
#else
|
|
void __cdecl start_callback_threadMPEG(callback_paramMPEG *callback_par)
|
|
#endif
|
|
{
|
|
(callback_par->fct)(callback_par->param);
|
|
|
|
GlobalFree(callback_par);
|
|
|
|
/*return 0;*/
|
|
}
|
|
/*fct appelée par genere en cas de Callback*/
|
|
/**buffer_dispo dans esi*/
|
|
void __stdcall start_callbackMPEG(SND_tdstMPEGVoice* pVoice)
|
|
{
|
|
/* BUFFER_DISPO *buffer;*/
|
|
/* DWORD id_thread;*/
|
|
callback_paramMPEG *callback_par;
|
|
|
|
callback_par=GlobalAlloc(GMEM_FIXED,sizeof(callback_paramMPEG));
|
|
callback_par->fct=pVoice->pfnCallBack;
|
|
callback_par->param=pVoice->ulParam;
|
|
|
|
/*CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)start_callback_thread,param,0,&id_thread);*/
|
|
#if defined(__WATCOMC__) && (__WATCOMC__<1100)
|
|
_beginthread(start_callback_threadMPEG,NULL,0,(void*)callback_par);
|
|
#else
|
|
_beginthread(start_callback_threadMPEG,0,(void*)callback_par);
|
|
#endif
|
|
}
|
|
|
|
#endif /*DISABLE_MPEG*/
|
|
|
|
long SND_CALL SND_fn_lPlayMPEG(tduRefRes num_sample,SampleParam *par,long prio,SND_td_pfn_vSoundCallback fn_callback,long par_callback)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
short wVolume;
|
|
SND_tdstMPEGVoice *pVoice;
|
|
tdstSampleMemory *pMemory;
|
|
tdstSampleStreaming *pStream;
|
|
tdstTypeSampleMem *pSample = &(num_sample.pstPtr->uRes.stSample);
|
|
|
|
if (bIsMPEGOk)
|
|
{
|
|
if (bIsClientPaused) {
|
|
SND_fn_vResumeBufferSxd(ulIdBufferClient);
|
|
bIsClientPaused = FALSE;
|
|
}
|
|
|
|
/*_RPT0(_CRT_WARN,"PLAY---------------\n");*/
|
|
if (pSample->bStream) {
|
|
pStream = &(pSample->uData.stStream);
|
|
pVoice = SND_fn_pSampleAllocateMPEGVoiceFile(pStream->szFileName,pStream->ulOffsetFirst);
|
|
if (pVoice) {
|
|
if (pSample->bVolable)
|
|
wVolume = (par->ucVol*num_sample.pstPtr->ucVolume)>>7;
|
|
else
|
|
wVolume = num_sample.pstPtr->ucVolume;
|
|
|
|
pVoice->ucVolume = num_sample.pstPtr->ucVolume;
|
|
pVoice->ucCurrentVolume = (unsigned char)wVolume;
|
|
pVoice->ucVolumeIndex = ucVolume[wVolume];
|
|
pVoice->bVolable = pSample->bVolable;
|
|
if (pVoice->pAssociatedVoice) {
|
|
pVoice->pAssociatedVoice->ucVolume = num_sample.pstPtr->ucVolume;
|
|
pVoice->pAssociatedVoice->ucCurrentVolume = (unsigned char)wVolume;
|
|
pVoice->pAssociatedVoice->ucVolumeIndex = ucVolume[wVolume];
|
|
pVoice->pAssociatedVoice->bVolable = pSample->bVolable;
|
|
}
|
|
if (fn_callback) {
|
|
pVoice->pfnCallBack = fn_callback;
|
|
pVoice->ulParam = par_callback;
|
|
}
|
|
else
|
|
pVoice->pfnCallBack = NULL;
|
|
|
|
MPEGCurrentRes[((unsigned long)pVoice-(unsigned long)MPEGvoices)/sizeof(SND_tdstMPEGVoice)]=num_sample.pstPtr;
|
|
|
|
return (long)pVoice;
|
|
}
|
|
} else {
|
|
pMemory = &(pSample->uData.stMem);
|
|
pVoice = SND_fn_pSampleAllocateMPEGVoiceMem(pMemory->pvPtrFirst,pMemory->ulNbEch);
|
|
if (pVoice) {
|
|
if (pSample->bVolable)
|
|
wVolume = (par->ucVol*num_sample.pstPtr->ucVolume)>>7;
|
|
else
|
|
wVolume = num_sample.pstPtr->ucVolume;
|
|
|
|
pVoice->ucVolume = num_sample.pstPtr->ucVolume;
|
|
pVoice->ucCurrentVolume = (unsigned char)wVolume;
|
|
pVoice->ucVolumeIndex = ucVolume[wVolume];
|
|
pVoice->bVolable = pSample->bVolable;
|
|
if (pVoice->pAssociatedVoice) {
|
|
pVoice->pAssociatedVoice->ucVolume = num_sample.pstPtr->ucVolume;
|
|
pVoice->pAssociatedVoice->ucCurrentVolume = (unsigned char)wVolume;
|
|
pVoice->pAssociatedVoice->ucVolumeIndex = ucVolume[wVolume];
|
|
pVoice->pAssociatedVoice->bVolable = pSample->bVolable;
|
|
}
|
|
|
|
if (fn_callback) {
|
|
pVoice->pfnCallBack = fn_callback;
|
|
pVoice->ulParam = par_callback;
|
|
}
|
|
else
|
|
pVoice->pfnCallBack = NULL;
|
|
|
|
MPEGCurrentRes[((unsigned long)pVoice-(unsigned long)MPEGvoices)/sizeof(SND_tdstMPEGVoice)]=num_sample.pstPtr;
|
|
|
|
return (long)pVoice;
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
return C_PLAY_FAILED;
|
|
#endif /*DISABLE_MPEG*/
|
|
return C_PLAY_FAILED;
|
|
}
|
|
|
|
void SND_CALL SND_fn_vRemoveCallbackMPEG(long voice)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
SND_tdstMPEGVoice *pVoice;
|
|
if (voice && voice!=C_PLAY_FAILED) {
|
|
pVoice = (SND_tdstMPEGVoice*)voice;
|
|
if (pVoice->pfnCallBack) {
|
|
pVoice->pfnCallBack = NULL;
|
|
pVoice->ulParam = 0;
|
|
}
|
|
}
|
|
#endif /*DISABLE_MPEG*/
|
|
}
|
|
|
|
SndBool SND_CALL SND_fn_bSetParamMPEG(long voice,SampleParam *par)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
SND_tdstMPEGVoice *pVoice;
|
|
short wInitialVol;
|
|
|
|
if (voice && voice!=C_PLAY_FAILED) {
|
|
pVoice = (SND_tdstMPEGVoice*)voice;
|
|
if((!pVoice->bIsPlaying)&&(!pVoice->bIsFinishing)) {
|
|
SND_fn_bFreeMPEGVoice(pVoice);
|
|
if (pVoice->pfnCallBack) {
|
|
start_callbackMPEG(pVoice);
|
|
}
|
|
pVoice->pfnCallBack = NULL;
|
|
|
|
return FALSE;
|
|
} else {
|
|
/* do modifications...*/
|
|
if (pVoice->bVolable) {
|
|
wInitialVol = pVoice->ucVolume;
|
|
wInitialVol *= par->ucVol;
|
|
wInitialVol >>= 7;
|
|
|
|
pVoice->ucCurrentVolume = (unsigned char)wInitialVol;
|
|
pVoice->ucVolumeIndex = ucVolume[wInitialVol];
|
|
if (pVoice->pAssociatedVoice)
|
|
{
|
|
pVoice->pAssociatedVoice->ucCurrentVolume = (unsigned char)wInitialVol;
|
|
pVoice->pAssociatedVoice->ucVolumeIndex = ucVolume[wInitialVol];
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
return TRUE;
|
|
#else
|
|
return FALSE;
|
|
#endif /*DISABLE_MPEG*/
|
|
}
|
|
|
|
SndBool SND_CALL SND_fn_bTestIsPlayingMPEG(long voice)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
SND_tdstMPEGVoice *pVoice;
|
|
if (voice && voice!=C_PLAY_FAILED) {
|
|
pVoice = (SND_tdstMPEGVoice*)voice;
|
|
if((!pVoice->bIsPlaying)&&(!pVoice->bIsFinishing)) {
|
|
SND_fn_bFreeMPEGVoice(pVoice);
|
|
if (pVoice->pfnCallBack) {
|
|
start_callbackMPEG(pVoice);
|
|
}
|
|
pVoice->pfnCallBack = NULL;
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
#else
|
|
return FALSE;
|
|
#endif /*DISABLE_MPEG*/
|
|
}
|
|
|
|
void SND_CALL SND_fn_vStopMPEG(long voice)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
SND_tdstMPEGVoice *pVoice;
|
|
|
|
if (voice && voice!=C_PLAY_FAILED) {
|
|
pVoice = (SND_tdstMPEGVoice*)voice;
|
|
pVoice->bIsPlaying = FALSE;
|
|
|
|
while(bInMPEGDecomp) {
|
|
Sleep(30);
|
|
}
|
|
|
|
SND_fn_bFreeMPEGVoice(pVoice);
|
|
if (pVoice->pfnCallBack) {
|
|
start_callbackMPEG(pVoice);
|
|
}
|
|
pVoice->pfnCallBack = NULL;
|
|
|
|
}
|
|
#endif /*DISABLE_MPEG*/
|
|
}
|
|
|
|
void SND_CALL SND_fn_vPauseMPEG(long voice)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
if (!bIsClientPaused) {
|
|
SND_fn_vPauseBufferSxd(ulIdBufferClient);
|
|
bIsClientPaused = TRUE;
|
|
}
|
|
|
|
/*
|
|
if (voice) {
|
|
((SND_tdstMPEGVoice*)voice)->bIsPaused = TRUE;
|
|
}
|
|
*/
|
|
#endif /*DISABLE_MPEG*/
|
|
}
|
|
|
|
void SND_CALL SND_fn_vResumeMPEG(long voice)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
/*on réactive la voie...*/
|
|
/*
|
|
if (voice) {
|
|
((SND_tdstMPEGVoice*)voice)->bIsPaused = FALSE;
|
|
}
|
|
*/
|
|
|
|
/*...puis on relance le buffer client*/
|
|
if (bIsClientPaused) {
|
|
SND_fn_vResumeBufferSxd(ulIdBufferClient);
|
|
bIsClientPaused = FALSE;
|
|
}
|
|
#endif /*DISABLE_MPEG*/
|
|
}
|
|
|
|
|
|
int SND_CALL SND_fn_iInitMPEG(SND_tdstInitStruct *pInitStruct)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
SND_tdstFormat formatclient;
|
|
SND_tdstCallback callback;
|
|
int i;
|
|
|
|
#if defined(_DLL_COMPILATION_MODE)
|
|
SND_DllInitEntryPoints_StaticFunctions((HMODULE)pInitStruct->hProcessInstance );
|
|
SND_DllInitEntryPoints_WavFunctions(SND_hWavModule);
|
|
#endif
|
|
|
|
for (i=0;i<(kNumVoice+1)*2;i++)
|
|
{
|
|
MPEGCurrentRes[i]=NULL;
|
|
}
|
|
|
|
if(SND_fn_bInitMPEG()) {
|
|
if(SND_fn_bStartMPEGEngine()) {
|
|
formatclient.eZip=SAMPLE_PCM;
|
|
formatclient.uFormat.stPCM.ulNbSamples=0;
|
|
/*formatclient.uFormat.stPCM.ulNbSamples=32*kFrameSize;*/
|
|
formatclient.uFormat.stPCM.uwResolution=16;
|
|
formatclient.uFormat.stPCM.uwNbChannels=2;
|
|
// formatclient.uFormat.stPCM.ulFreq=44100;
|
|
formatclient.uFormat.stPCM.ulFreq=M_SND_MPEG_BUFFERFREQ;
|
|
memset(&callback,0,sizeof(callback));
|
|
callback.eType=BUFFER_SYNCHRONE;
|
|
callback.uCallback.CallbackASynchrone=SND_fn_vRefreshMPEG;
|
|
ulIdBufferClient=SND_fn_lCreateNewBufferExSxd(&formatclient,&callback,NULL,0);
|
|
/*ulIdBufferClient = SND_fn_lCreateNewBufferSxd(32*kFrameSize,16,2,44100,NULL,SND_fn_vRefreshMPEG,0);*/
|
|
/*ulIdBufferClient = SND_fn_lCreateNewBufferSxd(32*kFrameSize,16,2,M_SND_MPEG_BUFFERFREQ,NULL,SND_fn_vRefreshMPEG,0);*/
|
|
bIsMPEGReleased = FALSE;
|
|
bIsClientPaused= FALSE;
|
|
if (ulIdBufferClient==C_PLAY_FAILED)
|
|
return FALSE;
|
|
|
|
bIsMPEGOk=TRUE;
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
#else
|
|
return C_INIT_FAILED;
|
|
#endif /*DISABLE_MPEG*/
|
|
}
|
|
|
|
SndBool SND_CALL SND_fn_bTestInitMPEG(void)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
return SND_fn_bInitDone();
|
|
#else
|
|
return FALSE;
|
|
#endif /*DISABLE_MPEG*/
|
|
}
|
|
|
|
void SND_CALL SND_fn_vDesInitMPEG(void)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
SND_fn_vDeleteBufferSxd(ulIdBufferClient);
|
|
SND_fn_bDesInitMPEG();
|
|
#endif /*DISABLE_MPEG*/
|
|
}
|
|
|
|
|
|
tduRefRes SND_CALL SND_fn_tdGetResForVoiceMPEG(long voice)
|
|
{
|
|
tduRefRes r={0};
|
|
return r;
|
|
}
|
|
|
|
|
|
void SND_CALL SND_fn_vConvertResDiskToMemMPEG(tdstBlockResourceDisk *disk
|
|
,tdstBlockResourceMem *mem
|
|
,void* ptrBegin)
|
|
{
|
|
snd_assert(disk->eType==TYPE_SAMPLE);
|
|
snd_assert(disk->uRes.stSample.eZip==SAMPLE_MPEG);
|
|
|
|
mem->Id=disk->Id;
|
|
mem->eType=disk->eType;
|
|
mem->eStorage=disk->eStorage;
|
|
mem->ucVolume=disk->ucVolume;
|
|
mem->bIsLoaded=TRUE;
|
|
|
|
mem->uRes.stSample.eZip=SAMPLE_MPEG;
|
|
#ifndef DISABLE_MPEG
|
|
/*partie spécifique au type de ressource*/
|
|
|
|
/**/
|
|
mem->uRes.stSample.bPitchable=FALSE;
|
|
mem->uRes.stSample.bVolable=disk->uRes.stSample.bVolable;
|
|
mem->uRes.stSample.bPanable=FALSE;
|
|
mem->uRes.stSample.bSpacable=FALSE;
|
|
mem->uRes.stSample.bReverbable=FALSE;
|
|
mem->uRes.stSample.bStream=disk->uRes.stSample.bStream;
|
|
mem->uRes.stSample.bLoop=FALSE;
|
|
mem->uRes.stSample.ulInc0=0;
|
|
mem->uRes.stSample.uwResolution=16;
|
|
mem->uRes.stSample.uwNbChannels=disk->uRes.stSample.uwNbChannels;
|
|
|
|
if (disk->uRes.stSample.bStream)
|
|
{/*sample streamé*/
|
|
strcpy(mem->uRes.stSample.uData.stStream.szFileName,disk->uRes.stSample.czFileName);
|
|
mem->uRes.stSample.uData.stStream.ulOffsetFirst=disk->ulDataOffset;
|
|
mem->uRes.stSample.uData.stStream.ulOffsetLoop=0;
|
|
mem->uRes.stSample.uData.stStream.ulOffsetLast=disk->ulDataSize;
|
|
}
|
|
else
|
|
{/*sample non streamé*/
|
|
mem->uRes.stSample.uData.stMem.ulNbEchLoop=0;
|
|
mem->uRes.stSample.uData.stMem.ulNbEch=disk->ulDataSize;
|
|
|
|
if (ptrBegin!=NULL)
|
|
mem->uRes.stSample.uData.stMem.pvPtrFirst=(void*)((unsigned long)ptrBegin/*+disk->ulDataOffset*/);
|
|
else
|
|
mem->uRes.stSample.uData.stMem.pvPtrFirst=NULL;
|
|
}
|
|
/*le sample est prêt à l'emploi*/
|
|
#endif /*DISABLE_MPEG*/
|
|
}
|
|
|
|
#if !defined(NO_ACP_SCRIPT) || defined(_DLL_COMPILATION_MODE)
|
|
/*this function must be defined in Script/Hybrid or DLL mode*/
|
|
SndBool SND_CALL SND_fn_bLoadResScriptMPEG(tdstBlockResourceDisk *disk,tdstBlockResourceMem *mem)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
void* data;
|
|
char file_name[256];
|
|
unsigned long ulSize;
|
|
|
|
if (!disk->uRes.stSample.bStream)
|
|
{
|
|
/* for MMX compatibility size should be mod 8*/
|
|
ulSize = disk->ulDataSize;
|
|
ulSize >>= 3;
|
|
ulSize++;
|
|
ulSize <<=3;
|
|
|
|
data=SND_fn_pvMallocSnd(ulSize);
|
|
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,"");
|
|
SND_fn_vFreeSnd(data);
|
|
data=NULL;
|
|
}
|
|
}
|
|
else
|
|
data=NULL;
|
|
|
|
SND_fn_vConvertResDiskToMemMPEG(disk,mem,data);
|
|
|
|
/*en script, chaque ressources charge ces propres data (on ne tient pas compte de eStorage)*/
|
|
mem->eStorage=TYPE_EXTERNAL;
|
|
|
|
|
|
return TRUE;
|
|
#else
|
|
return FALSE;
|
|
#endif /*DISABLE_MPEG*/
|
|
}
|
|
#endif
|
|
|
|
SndBool SND_CALL SND_fn_bLoadResBinaryMPEG(tdstBlockResourceDisk *disk,tdstBlockResourceMem *mem,char *pDataBloc)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
void* pData;
|
|
char file_name[256];
|
|
unsigned long ulSize;
|
|
|
|
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 the BRMem:*/
|
|
pData=(void *)(pDataBloc +disk->ulDataOffset);
|
|
}
|
|
else
|
|
{ /* Sample is external: it must be loaded from a file:*/
|
|
ulSize = disk->ulDataSize;
|
|
ulSize >>= 3;
|
|
ulSize++;
|
|
ulSize <<=3;
|
|
pData=SND_fn_pvMallocSnd(ulSize);
|
|
SND_fn_vResolveFileName(disk->uRes.stSample.czFileName,file_name);
|
|
if (!SND_fn_bLoadDataInMem(pData,disk->ulDataSize,file_name,disk->ulDataOffset))
|
|
{
|
|
SND_fn_vDisplayError(E_uwSndErrorReadingFile,"");
|
|
SND_fn_vFreeSnd(pData);
|
|
pData=NULL;
|
|
}
|
|
}
|
|
|
|
}
|
|
else pData=NULL; /* Sample is streaming*/
|
|
SND_fn_vConvertResDiskToMemMPEG(disk,mem,pData);
|
|
return TRUE;
|
|
#else
|
|
return FALSE;
|
|
#endif /*DISABLE_MPEG*/
|
|
}
|
|
|
|
/*
|
|
void SND_CALL SND_fn_vLoadResFromDiskMPEG(tdstBlockResourceDisk* disk,tdstBlockResourceMem* mem)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
void* data;
|
|
char file_name[256];
|
|
unsigned long ulSize;
|
|
|
|
if (!disk->uRes.stSample.bStream)
|
|
{
|
|
// for MMX compatibility size should be mod 8
|
|
ulSize = disk->ulDataSize;
|
|
ulSize >>= 3;
|
|
ulSize++;
|
|
ulSize <<=3;
|
|
|
|
data=SND_fn_pvMallocSnd(ulSize);
|
|
SND_fn_vResolveFileName(disk->uRes.stSample.czFileName,file_name);
|
|
if (!SND_fn_bLoadDataInMem(data,disk->ulDataSize,file_name,0))
|
|
{
|
|
SND_fn_vDisplayError(E_uwSndErrorReadingFile,"");
|
|
SND_fn_vFreeSnd(data);
|
|
data=NULL;
|
|
}
|
|
}
|
|
else
|
|
data=NULL;
|
|
|
|
SND_fn_vConvertResDiskToMemMPEG(disk,mem,data);
|
|
#endif
|
|
}
|
|
*/
|
|
|
|
void SND_CALL SND_fn_vUnLoadResMPEG(tdstBlockResourceMem* mem)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
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;
|
|
#endif
|
|
}
|
|
|
|
SndBool SND_CALL SND_fn_bIsResLoadedMPEG(tdstBlockResourceMem *mem)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
if (mem->uRes.stSample.bStream)
|
|
return TRUE;/* Streaming sample is always "loaded"*/
|
|
else return (mem->uRes.stSample.uData.stMem.pvPtrFirst!=NULL);
|
|
#else
|
|
return FALSE;
|
|
#endif /*DISABLE_MPEG*/
|
|
}
|
|
|
|
/*
|
|
void SND_CALL SND_fn_vSetResUnloadedMPEG(tdstBlockResourceMem *pResMem)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
pResMem->uRes.stSample.bStream=FALSE;
|
|
pResMem->uRes.stSample.uData.stMem.pvPtrFirst=NULL;
|
|
#endif //DISABLE_MPEG
|
|
}
|
|
*/
|
|
|
|
/* THEMES*/
|
|
long SND_CALL SND_fn_lPlayTransitionMPEG(tduRefRes FirstRes,tduRefRes NextRes,SND_td_pfn_vSoundCallback transition_callback,long param_callback,SampleParam* par)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
short wVolume;
|
|
SND_tdstMPEGVoice *pVoice;
|
|
tdstSampleMemory *pMemory;
|
|
tdstSampleStreaming *pStream;
|
|
tdstTypeSampleMem *pSample = &(FirstRes.pstPtr->uRes.stSample);
|
|
|
|
snd_assert(FirstRes.pstPtr->uRes.stSample.eZip==SAMPLE_MPEG);
|
|
snd_assert(NextRes.pstPtr->uRes.stSample.eZip==SAMPLE_MPEG);
|
|
|
|
if (bIsMPEGOk)
|
|
{
|
|
/* STOP CURRENT THEME OR MPEG SOUND*/
|
|
/*SND_fnvStopAllVoicesMPEGTheme();*/
|
|
if (bIsClientPaused) {
|
|
SND_fn_vResumeBufferSxd(ulIdBufferClient);
|
|
bIsClientPaused = FALSE;
|
|
}
|
|
|
|
/* START FIRST VOICE...*/
|
|
if (pSample->bStream) {
|
|
pStream = &(pSample->uData.stStream);
|
|
pVoice = SND_fn_pSimpleAllocateMPEGVoiceFile(pStream->szFileName,pStream->ulOffsetFirst);
|
|
if (pVoice) {
|
|
if (transition_callback) {
|
|
pVoice->pfnCallBack = transition_callback;
|
|
pVoice->ulParam = param_callback;
|
|
}
|
|
else
|
|
pVoice->pfnCallBack = NULL;
|
|
|
|
} else return C_PLAY_FAILED;
|
|
} else {
|
|
pMemory = &(pSample->uData.stMem);
|
|
pVoice = SND_fn_pSimpleAllocateMPEGVoiceMem(pMemory->pvPtrFirst,pMemory->ulNbEch);
|
|
if (pVoice) {
|
|
if (transition_callback) {
|
|
pVoice->pfnCallBack = transition_callback;
|
|
pVoice->ulParam = param_callback;
|
|
}
|
|
else
|
|
pVoice->pfnCallBack = NULL;
|
|
|
|
} else return C_PLAY_FAILED;
|
|
}
|
|
|
|
/* SET SECOND VOICE...*/
|
|
pSample = &(NextRes.pstPtr->uRes.stSample);
|
|
if (pSample->bStream) {
|
|
pStream = &(pSample->uData.stStream);
|
|
pVoice = SND_fn_pAllocateMPEGVoiceFile(pStream->szFileName,pStream->ulOffsetFirst);
|
|
if (pVoice) {
|
|
if (transition_callback) {
|
|
pVoice->pfnCallBack = transition_callback;
|
|
pVoice->ulParam = param_callback;
|
|
}
|
|
else
|
|
pVoice->pfnCallBack = NULL;
|
|
|
|
} else return C_PLAY_FAILED;
|
|
} else {
|
|
pMemory = &(pSample->uData.stMem);
|
|
pVoice = SND_fn_pAllocateMPEGVoiceMem(pMemory->pvPtrFirst,pMemory->ulNbEch);
|
|
if (pVoice) {
|
|
if (transition_callback) {
|
|
pVoice->pfnCallBack = transition_callback;
|
|
pVoice->ulParam = param_callback;
|
|
}
|
|
else
|
|
pVoice->pfnCallBack = NULL;
|
|
|
|
} else return C_PLAY_FAILED;
|
|
}
|
|
|
|
wVolume = par->ucVol;/*NextRes.pstPtr->ucVolume;*/
|
|
if (wVolume < 0) wVolume =0;
|
|
if (wVolume > 127) wVolume = 127;
|
|
|
|
pSwapVoice[0]->ucVolume = (unsigned char)wVolume;/*NextRes.pstPtr->ucVolume;*/
|
|
pSwapVoice[0]->ucCurrentVolume = (unsigned char)wVolume;
|
|
pSwapVoice[0]->ucVolumeIndex = ucVolume[wVolume];
|
|
pSwapVoice[1]->ucVolume = (unsigned char)wVolume;/*NextRes.pstPtr->ucVolume;*/
|
|
pSwapVoice[1]->ucCurrentVolume = (unsigned char)wVolume;
|
|
pSwapVoice[1]->ucVolumeIndex = ucVolume[wVolume];
|
|
|
|
if (pSwapVoice[0]->pAssociatedVoice) {
|
|
pSwapVoice[0]->pAssociatedVoice->ucVolume = (unsigned char)wVolume;/*NextRes.pstPtr->ucVolume;*/
|
|
pSwapVoice[0]->pAssociatedVoice->ucCurrentVolume = (unsigned char)wVolume;/*NextRes.pstPtr->ucVolume;*/
|
|
pSwapVoice[0]->pAssociatedVoice->ucVolumeIndex = ucVolume[wVolume];
|
|
}
|
|
if (pSwapVoice[1]->pAssociatedVoice) {
|
|
pSwapVoice[1]->pAssociatedVoice->ucVolume = (unsigned char)wVolume;/*NextRes.pstPtr->ucVolume;*/
|
|
pSwapVoice[1]->pAssociatedVoice->ucCurrentVolume = (unsigned char)wVolume;/*NextRes.pstPtr->ucVolume;*/
|
|
pSwapVoice[1]->pAssociatedVoice->ucVolumeIndex = ucVolume[wVolume];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
else
|
|
return C_PLAY_FAILED;
|
|
#else
|
|
return C_PLAY_FAILED;
|
|
#endif /*DISABLE_MPEG*/
|
|
}
|
|
|
|
SndBool SND_CALL SND_fn_bSetParamTransitionMPEG(long voice,SampleParam* par)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
/*SND_tdstMPEGVoice *pVoice;*/
|
|
short wVolume;
|
|
|
|
wVolume = par->ucVol;/*NextRes.pstPtr->ucVolume;*/
|
|
if (wVolume < 0) wVolume =0;
|
|
if (wVolume > 127) wVolume = 127;
|
|
|
|
pSwapVoice[0]->ucVolume = (unsigned char)wVolume;/*NextRes.pstPtr->ucVolume;*/
|
|
pSwapVoice[0]->ucCurrentVolume = (unsigned char)wVolume;
|
|
pSwapVoice[0]->ucVolumeIndex = ucVolume[wVolume];
|
|
pSwapVoice[1]->ucVolume = (unsigned char)wVolume;/*NextRes.pstPtr->ucVolume;*/
|
|
pSwapVoice[1]->ucCurrentVolume = (unsigned char)wVolume;
|
|
pSwapVoice[1]->ucVolumeIndex = ucVolume[wVolume];
|
|
|
|
if (pSwapVoice[0]->pAssociatedVoice) {
|
|
pSwapVoice[0]->pAssociatedVoice->ucVolume = (unsigned char)wVolume;/*NextRes.pstPtr->ucVolume;*/
|
|
pSwapVoice[0]->pAssociatedVoice->ucCurrentVolume = (unsigned char)wVolume;/*NextRes.pstPtr->ucVolume;*/
|
|
pSwapVoice[0]->pAssociatedVoice->ucVolumeIndex = ucVolume[wVolume];
|
|
}
|
|
if (pSwapVoice[1]->pAssociatedVoice) {
|
|
pSwapVoice[1]->pAssociatedVoice->ucVolume = (unsigned char)wVolume;/*NextRes.pstPtr->ucVolume;*/
|
|
pSwapVoice[1]->pAssociatedVoice->ucCurrentVolume = (unsigned char)wVolume;/*NextRes.pstPtr->ucVolume;*/
|
|
pSwapVoice[1]->pAssociatedVoice->ucVolumeIndex = ucVolume[wVolume];
|
|
}
|
|
return TRUE;
|
|
#else
|
|
return FALSE;
|
|
#endif
|
|
}
|
|
|
|
tduRefRes SND_g_uFadeRes;
|
|
|
|
SndBool SND_CALL SND_fn_bSetNextTransitionMPEG(long voice,tduRefRes new_res)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
/*short wVolume;*/
|
|
SND_tdstMPEGVoice *pVoice;
|
|
tdstSampleMemory *pMemory;
|
|
tdstSampleStreaming *pStream;
|
|
tdstTypeSampleMem *pSample = &(new_res.pstPtr->uRes.stSample);
|
|
|
|
snd_assert(new_res.pstPtr->uRes.stSample.eZip==SAMPLE_MPEG);
|
|
|
|
/* char szTemp[256];*/
|
|
/* SET THE NEXT MPEG VOICE TO PLAY*/
|
|
if (pSample->bStream) {
|
|
pStream = &(pSample->uData.stStream);
|
|
|
|
pVoice = SND_fn_pAllocateMPEGVoiceFile(pStream->szFileName,pStream->ulOffsetFirst);
|
|
if (pVoice) {
|
|
pVoice->bVolable = pSample->bVolable;
|
|
|
|
} else return FALSE;
|
|
} else {
|
|
pMemory = &(pSample->uData.stMem);
|
|
pVoice = SND_fn_pAllocateMPEGVoiceMem(pMemory->pvPtrFirst,pMemory->ulNbEch);
|
|
if (pVoice) {
|
|
pVoice->bVolable = pSample->bVolable;
|
|
|
|
} else return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
#else
|
|
return FALSE;
|
|
#endif /*DISABLE_MPEG*/
|
|
}
|
|
|
|
SndBool SND_CALL SND_fn_bDoTransitionWithFadeMPEG2( long voice, tduRefRes new_res, SndReal rDuration )
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
SND_tdstMPEGVoice *pCurrentVoice,*pNextVoice;
|
|
unsigned long ulFadeSize,ulCurrentSizeLeft;
|
|
SndBool bFadeInPart;
|
|
int iFadeFrameNumber;
|
|
#ifndef M_FRED_DECREAU
|
|
_int64 _iFade;
|
|
#endif
|
|
|
|
if (bIsMPEGOk)
|
|
{
|
|
pCurrentVoice=pSwapVoice[0];
|
|
pNextVoice=pSwapVoice[1];
|
|
bFadeInPart=FALSE;
|
|
#ifdef M_FRED_DECREAU
|
|
ulFadeSize=32*2000; /* On voudrait fader sur 1300 miniframes de 32 samples*/
|
|
/* ulFadeSize=32*3000; // test avec 3 secondes..*/
|
|
#else
|
|
/*
|
|
* Estimate the fade duration in sample unit
|
|
*/
|
|
pCurrentVoice->rDuration = rDuration;
|
|
pNextVoice->rDuration = rDuration;
|
|
_iFade = rDuration;
|
|
_iFade = M_RealToIntSnd( M_MulIntRealSnd( _iFade, M_SND_MPEG_BUFFERFREQ - 32 * 48 ) );
|
|
ulFadeSize = (unsigned long)_iFade;
|
|
/*
|
|
* The Fade duration in sample must be a modulo of 32. Because in MPEG data are
|
|
* decompressed Frame after Frame, and a Frame length is 32 sample long
|
|
*/
|
|
ulFadeSize -= ulFadeSize % 32;
|
|
#endif
|
|
ulCurrentSizeLeft=pCurrentVoice->ulFinalSize-pCurrentVoice->ulPos;
|
|
|
|
/* Set bFadeInPart and ulFadeTime:*/
|
|
if (!pNextVoice->bIsPlaying)
|
|
{
|
|
bFadeInPart=TRUE; /* No next part->fade in part!*/
|
|
/* Adjust fade time with remaining time:*/
|
|
if (ulCurrentSizeLeft<ulFadeSize) ulFadeSize=ulCurrentSizeLeft;
|
|
}
|
|
else
|
|
{
|
|
if (ulCurrentSizeLeft>=ulFadeSize)
|
|
{ /* enough time left in this part to fade:*/
|
|
bFadeInPart=TRUE;
|
|
}
|
|
else
|
|
{ /* We'll fade on two parts:*/
|
|
if ((ulCurrentSizeLeft+pNextVoice->ulFinalSize)<ulFadeSize)
|
|
ulFadeSize=ulCurrentSizeLeft+pNextVoice->ulFinalSize;
|
|
bFadeInPart=FALSE;
|
|
}
|
|
}
|
|
/*
|
|
* Calculate the number of fade frame = iFadeFrameNumber
|
|
* Volume decrement. Decreament linearly the volume
|
|
* Set part as fading and fade parameters:
|
|
*/
|
|
iFadeFrameNumber=ulFadeSize/32;
|
|
pCurrentVoice->bIsFading=TRUE;
|
|
#if M_FRED_DECREAU
|
|
pCurrentVoice->iFadeIncrement=-((1<<16)/iFadeFrameNumber);
|
|
#else
|
|
pCurrentVoice->iFadeIncrement=-(rDuration/iFadeFrameNumber);
|
|
#endif
|
|
pCurrentVoice->iFadeVolume=(-pCurrentVoice->iFadeIncrement)*iFadeFrameNumber;
|
|
if( pCurrentVoice->pAssociatedVoice ) {
|
|
pCurrentVoice->pAssociatedVoice->bIsFading = TRUE;
|
|
pCurrentVoice->pAssociatedVoice->rDuration = rDuration;
|
|
pCurrentVoice->pAssociatedVoice->iFadeIncrement = pCurrentVoice->iFadeIncrement;
|
|
pCurrentVoice->pAssociatedVoice->iFadeVolume = pCurrentVoice->iFadeVolume;
|
|
}
|
|
if (bFadeInPart)
|
|
{
|
|
/* OutputDebugString("start of fade: fade in part\n");*/
|
|
/* Shorten current voice if necessary:*/
|
|
pCurrentVoice->ulFinalSize=pCurrentVoice->ulPos+ulFadeSize;
|
|
/* Set a new transition with the new_res:*/
|
|
SND_fn_bSetNextTransitionMPEG(voice,new_res);
|
|
SND_g_uFadeRes.pstPtr=NULL;
|
|
}
|
|
else
|
|
{ /* Fade in two parts:*/
|
|
/* OutputDebugString("start of fade: two parts fade\n");*/
|
|
SND_g_uFadeRes=new_res;
|
|
/* Shorten next voice if necessary:*/
|
|
pNextVoice->ulFinalSize=ulFadeSize-ulCurrentSizeLeft;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
#else
|
|
return FALSE;
|
|
#endif
|
|
}
|
|
|
|
SndBool SND_CALL SND_fn_bDoTransitionWithFadeMPEG( long voice, tduRefRes new_res )
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
return SND_fn_bDoTransitionWithFadeMPEG2( voice, new_res, M_FADE_DURATION_MPEG );
|
|
#endif /*DISABLE_MPEG*/
|
|
}
|
|
|
|
void SND_CALL SND_fn_vStopTransitionMPEG(long voice)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
SND_fnvStopAllVoicesMPEGTheme();
|
|
#endif /*DISABLE_MPEG*/
|
|
}
|
|
|
|
|
|
void SND_CALL SND_fn_vPauseTransitionMPEG(long voice)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
/*pSwapVoice[0]->bIsPaused = TRUE;*/
|
|
if (!bIsClientPaused && bIsMPEGOk) {
|
|
/* pSwapVoice[0]->bIsPaused = TRUE;*/
|
|
SND_fn_vPauseBufferSxd(ulIdBufferClient);
|
|
bIsClientPaused = TRUE;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void SND_CALL SND_fn_vResumeTransitionMPEG(long voice)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
/*pSwapVoice[0]->bIsPaused = FALSE;*/
|
|
if (bIsClientPaused && bIsMPEGOk) {
|
|
/* pSwapVoice[0]->bIsPaused = FALSE;*/
|
|
SND_fn_vResumeBufferSxd(ulIdBufferClient);
|
|
bIsClientPaused = FALSE;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
#ifndef NO_ACP_LDBIN
|
|
SndBool SND_CALL SND_fn_bCanFreeDataMPEG(void)
|
|
{
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
/*--------------------------------------------------
|
|
relache-reprise a chaud des drives
|
|
---------------------------------------------------------*/
|
|
void SND_CALL SND_fn_vReleaseDriverMPEG()
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
|
|
if (!bIsMPEGOk) return;
|
|
if (bIsMPEGReleased) return;
|
|
|
|
/* FAIRE TOUT CE QU'IL FAUT...*/
|
|
|
|
|
|
bIsMPEGReleased = TRUE;
|
|
#endif
|
|
}
|
|
|
|
void SND_CALL SND_fn_vRestoreDriverMPEG()
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
SndReal rBufferState;
|
|
if (!bIsMPEGOk) return;
|
|
if (!bIsMPEGReleased) return;
|
|
|
|
/* FAIRE TOUT CE QU'IL FAUT...*/
|
|
rBufferState=SND_fn_rGetPosBufferSxd(ulIdBufferClient);
|
|
if ((rBufferState==SND_C_POS_ENDED) || (rBufferState==SND_C_POS_UNKNOWN))
|
|
/*driver WAV perdu -> MPEG kaput*/
|
|
bIsMPEGOk=FALSE;
|
|
|
|
bIsMPEGReleased = FALSE;
|
|
#endif
|
|
}
|
|
|
|
/*---------------------------------------------------------*/
|
|
/* GetPos: retourne la position "théorique" de la ressource*/
|
|
/* exprimé en seconde depuis le début*/
|
|
/* différent du temps absolu (car pitch, dérive..)*/
|
|
/* Entrée: voie concernée*/
|
|
/* Sortie: temps en S (SndReal)*/
|
|
/*----------------------------------------------------------*/
|
|
SndReal SND_CALL SND_fn_rGetPosMPEG(long voice)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
SND_tdstMPEGVoice *pVoice;
|
|
long temp;
|
|
|
|
if (bIsMPEGOk && voice!=C_PLAY_FAILED && voice)
|
|
{
|
|
pVoice = (SND_tdstMPEGVoice*)voice;
|
|
if((pVoice->bIsPlaying) || (pVoice->bIsFinishing))
|
|
{
|
|
// temp=M_DoubleToRealSnd(((double)pVoice->ulPos/*-32.0*kFrameSize*/-480)/44100.);
|
|
temp=M_DoubleToRealSnd(((double)pVoice->ulPos/*-32.0*kFrameSize*/-480)/M_SND_MPEG_BUFFERFREQ.);
|
|
if (temp>0)
|
|
return temp;
|
|
else
|
|
return 0;
|
|
}
|
|
}
|
|
#endif
|
|
return SND_C_POS_UNKNOWN;
|
|
}
|
|
|
|
/*---------------------------------------------------------*/
|
|
/* GetLength: retourne la durée "théorique" de la ressource*/
|
|
/* exprimé en seconde (constant pour une ressource donnée)*/
|
|
/* Entrée: voie concernée*/
|
|
/* Sortie: durée en S (SndReal)*/
|
|
/*----------------------------------------------------------*/
|
|
SndReal SND_CALL SND_fn_rGetLengthMPEG(long voice)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
SND_tdstMPEGVoice *pVoice;
|
|
|
|
if (voice!=C_PLAY_FAILED && voice)
|
|
{
|
|
pVoice = (SND_tdstMPEGVoice*)voice;
|
|
if(pVoice->bIsPlaying)
|
|
// return SND_fn_rDivRealRealSnd(pVoice->ulFinalSize,44100);
|
|
return SND_fn_rDivRealRealSnd(pVoice->ulFinalSize,M_SND_MPEG_BUFFERFREQ);
|
|
}
|
|
#endif
|
|
return SND_C_LENGTH_UNKNOWN;
|
|
}
|
|
|
|
/*-------------------------------------------------*/
|
|
/* Fonction de synchro moteur*/
|
|
/* ne sert à rien pour MPEG*/
|
|
/*-------------------------------------------------*/
|
|
void SND_CALL SND_fn_vSynchroMPEG()
|
|
{
|
|
}
|
|
|
|
/*nouveau buffers clients*/
|
|
long SND_CALL SND_fn_lCreateNewBufferExMPEG(SND_tdstFormat* pformat,SND_tdstCallback* pCallback,SoundParam* par,long user_id)
|
|
{
|
|
return C_PLAY_FAILED;
|
|
}
|
|
|
|
long SND_CALL SND_fn_lGetPosBufferExMPEG(long id_buffer)
|
|
{
|
|
return SND_C_POS_UNKNOWN;
|
|
}
|
|
|
|
long SND_CALL SND_fn_lPushBufferExMPEG(long id_buffer,SND_tdstStackBuffer* pStack)
|
|
{
|
|
return C_PLAY_FAILED;
|
|
}
|
|
|
|
void SND_CALL SND_fn_vSetDefaultRollOffMPEG(RollOffParam* rolloff)
|
|
{
|
|
/*nothing to do in, this version*/
|
|
}
|
|
|
|
SndBool SND_CALL SND_fn_bCheckVersionResourceMPEG(tdstBlockResourceDisk *disk)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
SndBool SND_CALL SND_fn_bSetResourceStaticVolumeMPEG(tdstBlockResourceMem* pstRes,unsigned char ucVolume)
|
|
{
|
|
#ifndef DISABLE_MPEG
|
|
SND_tdstMPEGVoice *pVoice;
|
|
int i;
|
|
|
|
pstRes->ucVolume=ucVolume;
|
|
|
|
for (i=0,pVoice=&MPEGvoices[0];i<(kNumVoice+1)*2;i++,pVoice++)
|
|
{
|
|
if (MPEGCurrentRes[i]!=NULL)
|
|
if (MPEGCurrentRes[i]==pstRes)
|
|
{
|
|
MPEGvoices[i].ucVolume=ucVolume;
|
|
}
|
|
}
|
|
|
|
#endif /*DISABLE_MPEG*/
|
|
return TRUE;
|
|
}
|
|
|