reman3/Rayman_X/cpa/tempgrp/SND/src/mpeg/mpeg.cxx

1074 lines
34 KiB
C++
Raw Blame History

/*
// ================================================================
// MPEG.cxx
// Ubi Sound Studios
// 24/03/1997
// Guillaume Michel
// ================================================================
*/
//added by stephane RONSE on 04/29/98
// must be set FALSE each time a new sound begin
// will be set to TRUE each time silence beginn(i.e. no more sound are played) and so the SynhtesisBuffer is reinitilized
SndBool bSynthesisBufferCleaned=TRUE;
//-------------------------------------------------------------------------
// Description : Init MPEG Engine
//-------------------------------------------------------------------------
// MUST BE DONE ONCE AT THE BEGINING OF THE PROGRAM
//-------------------------------------------------------------------------
// Input : None
// Output : SndBool
//-------------------------------------------------------------------------
// Creation date : 18/03/97 Author : Guillaume Michel
//-------------------------------------------------------------------------
// Modifications :
// Modification Date : Author :
//-------------------------------------------------------------------------
SndBool SND_fn_bInitMPEG()
{
if (!SND_fn_bTestSnd_Processor())
{
SND_fn_vDisplayError(E_uwSndBadHostConfiguration,C_PROCESSOR_WANTED);
return C_INIT_FAILED;
}
#ifdef _PROFILE_MFC_
QueryPerformanceFrequency(&t0);
iTotalTime = iNumTime = 0;
#endif
SND_fn_vInitSignalProcessing();
return (bInitDone = SND_fn_bInitMPEGMemory());
}
SndBool SND_fn_bInitDone()
{
return bInitDone;
}
//-------------------------------------------------------------------------
// Description : free memory for decrompression...
//-------------------------------------------------------------------------
// DO ALL DESALLOC (CALLED ONCE AT THE END OF THE APPLICATION)
//-------------------------------------------------------------------------
// Input : voice pointer and number of channel
// Output : SndBool
//-------------------------------------------------------------------------
// Creation date : 18/03/97 Author : Guillaume Michel
//-------------------------------------------------------------------------
// Modifications :
// Modification Date : Author :
//-------------------------------------------------------------------------
SndBool SND_fn_bFreeMPEGMemory(SND_tdstMPEGVoice* pVoice)
{
snd_assert(pVoice);
if (pVoice->pucBitAlloc) {
SND_fn_vFreeSnd(pVoice->pucBitAlloc);
pVoice->pucBitAlloc = NULL;
pVoice->pucScaleFactorPattern = NULL;
pVoice->pucScaleFactor = NULL;
}
if (pVoice->pdDiviseur) {
SND_fn_vFreeSnd(pVoice->pdDiviseur);
pVoice->pdDiviseur = NULL;
pVoice->pdScaleFactor = NULL;
pVoice->pdSumFactor = NULL;
}
if (pVoice->pwSample) {
SND_fn_vFreeSnd(pVoice->pwSample);
pVoice->pwSample = NULL;
}
pVoice->pfnCallBack = NULL;
return TRUE;
}
//-------------------------------------------------------------------------
// Description : Init MPEG Engine before using it
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
// Input : None
// Output : None
//-------------------------------------------------------------------------
// Creation date : 24/03/97 Author : Guillaume Michel
//-------------------------------------------------------------------------
// Modifications :
// Modification Date : Author :
//-------------------------------------------------------------------------
SndBool SND_fn_bStartMPEGEngine()
{
int i;
SND_tdstMPEGVoice* pVoice;
// MPEG Engine INITS
for (i = 0; i < (kNumVoice+1); i++) {
pVoice = &MPEGvoices[i];
pVoice->bIsFree = TRUE;
pVoice->bIsMuted = FALSE;
pVoice->bIsPlaying = FALSE;
pVoice->bIsFading = FALSE;
pVoice->iFadeVolume = 0;
pVoice->iFadeIncrement = 0;
pVoice->bIsPaused = FALSE;
pVoice->bIsOneShot = FALSE;
pVoice->bIsSurround = FALSE;
pVoice->bIsFullSurround = FALSE;
pVoice->bIsFinishing = FALSE;
pVoice->ulNumSampleBeforeEnd = 0;
SND_fn_bInitBitStream(&(pVoice->bitstream));
pVoice->pfnCallBack = NULL;
}
pSwapVoice[0] = &MPEGvoices[0]; // playing voice
pSwapVoice[1] = &MPEGvoices[1]; // waiting voice
iOffset[0] = iOffset[1] = 64;
bSwitchPart = FALSE;
iMiniFrameTheme=12;
iIndexTheme=3;
iMiniFrameSample=12;
iIndexSample=3;
return TRUE;
}
//-------------------------------------------------------------------------
// Description : Open a new voice from File
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
// Input : filename and number of channel
// Output : voice pointer
//-------------------------------------------------------------------------
// Creation date : 18/03/97 Author : Guillaume Michel
//-------------------------------------------------------------------------
// Modifications :
// Modification Date : Author :
//-------------------------------------------------------------------------
SND_tdstMPEGVoice* SND_fn_pAllocateMPEGVoiceFile(char* pFileName, unsigned long ulOffset)
{
int i;
unsigned long param;
SND_td_pfn_vSoundCallback cb;
SND_tdstMPEGVoice* pCurrentVoice;
if (pSwapVoice[0]->bIsFree) {
i = 0; // La voie principale est libre: on d<>marre dessus
} else {
// on <20>crase la voie secondaire (imp<6D>ratif th<74>me)
SND_fn_bFreeMPEGVoice(pSwapVoice[1]);
i = 1;
}
pCurrentVoice = pSwapVoice[i];
cb = pCurrentVoice->pfnCallBack;
param = pCurrentVoice->ulParam;
if (SND_fn_bOpenBitStreamFile(pCurrentVoice->pRealBitStream,pFileName,ulOffset)) {
// This voice will be used...
pCurrentVoice->bIsFree = FALSE;
//pCurrentVoice->ucVolume = 127;
//pCurrentVoice->ucVolumeIndex = 0;
pCurrentVoice->bIsPaused = pCurrentVoice->bIsMuted = FALSE;
pCurrentVoice->ulPos = 0;
pCurrentVoice->ulFinalSize = pCurrentVoice->pRealBitStream->ulFinalSize ;
pCurrentVoice->bIsFullSurround = (pCurrentVoice->pRealBitStream->ulDolbyMark == 'SUR2');
pCurrentVoice->bIsSurround = ((pCurrentVoice->pRealBitStream->ulDolbyMark == 'SUR2') ||
(pCurrentVoice->pRealBitStream->ulDolbyMark == 'SUR1'));
if (pCurrentVoice->bIsSurround) {
pCurrentVoice->pAssociatedVoice = pCurrentVoice + (kNumVoice+1);
pCurrentVoice->pAssociatedVoice->bIsPlaying = TRUE;
//pCurrentVoice->pAssociatedVoice->ucVolume = 127;
//pCurrentVoice->pAssociatedVoice->ucVolumeIndex = 0;
pCurrentVoice->pAssociatedVoice->bIsMuted = FALSE;
} else {
pCurrentVoice->pAssociatedVoice = NULL;
}
pCurrentVoice->pfnCallBack = cb;
pCurrentVoice->ulParam = param;
pCurrentVoice->bIsPlaying = TRUE;
pCurrentVoice->bIsFinishing = FALSE;
pCurrentVoice->ulNumSampleBeforeEnd = 0;
pCurrentVoice->bIsFading = FALSE;
pCurrentVoice->iFadeVolume = 0;
pCurrentVoice->iFadeIncrement = 0;
return pCurrentVoice;
} else return NULL;
}
//-------------------------------------------------------------------------
// Description : Open a new voice from memory
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
// Input : buffer pointer, buffer size, voice pointer and number of channel
// Output : voice pointer
//-------------------------------------------------------------------------
// Creation date : 18/03/97 Author : Guillaume Michel
//-------------------------------------------------------------------------
// Modifications :
// Modification Date : Author :
//-------------------------------------------------------------------------
SND_tdstMPEGVoice* SND_fn_pAllocateMPEGVoiceMem(unsigned char* pBuffer, unsigned long ulSize)
{
int i;
unsigned long param;
SND_td_pfn_vSoundCallback cb;
SND_tdstMPEGVoice* pCurrentVoice;
if (pSwapVoice[0]->bIsFree) {
i = 0;
} else {
// on <20>crase la voie secondaire (imp<6D>ratif th<74>me)
SND_fn_bFreeMPEGVoice(pSwapVoice[1]);
i = 1;
}
pCurrentVoice = pSwapVoice[i];
cb = pCurrentVoice->pfnCallBack;
param = pCurrentVoice->ulParam;
if (SND_fn_bOpenBitStreamMem(pCurrentVoice->pRealBitStream,pBuffer,ulSize)) {
// This voice will be used...
pCurrentVoice->bIsFree = FALSE;
//pCurrentVoice->ucVolume = 127;
//pCurrentVoice->ucVolumeIndex = 0;
pCurrentVoice->bIsPaused = pCurrentVoice->bIsMuted = FALSE;
pCurrentVoice->ulPos = 0;
pCurrentVoice->ulFinalSize = pCurrentVoice->pRealBitStream->ulFinalSize ;
pCurrentVoice->bIsFullSurround = (pCurrentVoice->pRealBitStream->ulDolbyMark == 'SUR2');
pCurrentVoice->bIsSurround = (pCurrentVoice->pRealBitStream->ulDolbyMark == 'SUR2') ||
(pCurrentVoice->pRealBitStream->ulDolbyMark == 'SUR1');
if (pCurrentVoice->bIsSurround) {
pCurrentVoice->pAssociatedVoice = pCurrentVoice + (kNumVoice+1);
pCurrentVoice->pAssociatedVoice->bIsPlaying = TRUE;
//pCurrentVoice->pAssociatedVoice->ucVolume = 127;
//pCurrentVoice->pAssociatedVoice->ucVolumeIndex = 0;
pCurrentVoice->pAssociatedVoice->bIsMuted = FALSE;
} else {
pCurrentVoice->pAssociatedVoice = NULL;
}
pCurrentVoice->pfnCallBack = cb;
pCurrentVoice->ulParam = param;
pCurrentVoice->bIsPlaying = TRUE;
pCurrentVoice->bIsFinishing = FALSE;
pCurrentVoice->ulNumSampleBeforeEnd = 0;
pCurrentVoice->bIsFading = FALSE;
pCurrentVoice->iFadeVolume = 0;
pCurrentVoice->iFadeIncrement = 0;
return pCurrentVoice;
} else return NULL;
}
//-------------------------------------------------------------------------
// Description : Open a new voice from File
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
// Input : filename and number of channel
// Output : voice pointer
//-------------------------------------------------------------------------
// Creation date : 18/03/97 Author : Guillaume Michel
//-------------------------------------------------------------------------
// Modifications :
// Modification Date : Author :
//-------------------------------------------------------------------------
SND_tdstMPEGVoice* SND_fn_pSimpleAllocateMPEGVoiceFile(char* pFileName, unsigned long ulOffset)
{
SND_tdstMPEGVoice* pCurrentVoice;
pCurrentVoice = pSwapVoice[0];
if (!pCurrentVoice->bIsFree) {
return NULL;
}
//added by stepahen RONSE on 04/29/98
bSynthesisBufferCleaned=FALSE;
if (SND_fn_bOpenBitStreamFile(pCurrentVoice->pRealBitStream,pFileName, ulOffset)) {
// This voice will be used...
pCurrentVoice->bIsFree = FALSE;
pCurrentVoice->bIsPlaying = TRUE;
//pCurrentVoice->ucVolume = 127;
//pCurrentVoice->ucVolumeIndex = 0;
pCurrentVoice->bIsPaused = pCurrentVoice->bIsMuted = FALSE;
pCurrentVoice->bIsFullSurround = (pCurrentVoice->pRealBitStream->ulDolbyMark == 'SUR2');
pCurrentVoice->bIsSurround = (pCurrentVoice->pRealBitStream->ulDolbyMark == 'SUR2') ||
(pCurrentVoice->pRealBitStream->ulDolbyMark == 'SUR1');
if (pCurrentVoice->bIsSurround) {
pCurrentVoice->pAssociatedVoice = pCurrentVoice + (kNumVoice+1);
pCurrentVoice->pAssociatedVoice->bIsPlaying = TRUE;
//pCurrentVoice->pAssociatedVoice->ucVolume = 127;
//pCurrentVoice->pAssociatedVoice->ucVolumeIndex = 0;
pCurrentVoice->pAssociatedVoice->bIsMuted = FALSE;
} else {
pCurrentVoice->pAssociatedVoice = NULL;
}
pCurrentVoice->ulPos = 0;
pCurrentVoice->ulFinalSize = pCurrentVoice->pRealBitStream->ulFinalSize ;
pCurrentVoice->bIsFinishing = FALSE;
pCurrentVoice->ulNumSampleBeforeEnd = 0;
pCurrentVoice->bIsFading = FALSE;
pCurrentVoice->iFadeVolume = 0;
pCurrentVoice->iFadeIncrement = 0;
return pCurrentVoice;
} else return NULL;
}
//-------------------------------------------------------------------------
// Description : Open a new voice from memory
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
// Input : buffer pointer, buffer size, voice pointer and number of channel
// Output : voice pointer
//-------------------------------------------------------------------------
// Creation date : 18/03/97 Author : Guillaume Michel
//-------------------------------------------------------------------------
// Modifications :
// Modification Date : Author :
//-------------------------------------------------------------------------
SND_tdstMPEGVoice* SND_fn_pSimpleAllocateMPEGVoiceMem(unsigned char* pBuffer, unsigned long ulSize)
{
SND_tdstMPEGVoice* pCurrentVoice;
pCurrentVoice = pSwapVoice[0];
if (!pCurrentVoice->bIsFree) {
return NULL;
}
//added by stepahen RONSE on 04/29/98
bSynthesisBufferCleaned=FALSE;
if (SND_fn_bOpenBitStreamMem(pCurrentVoice->pRealBitStream,pBuffer,ulSize)) {
// This voice will be used...
pCurrentVoice->bIsFree = FALSE;
pCurrentVoice->bIsPlaying = TRUE;
//pCurrentVoice->ucVolume = 127;
//pCurrentVoice->ucVolumeIndex = 0;
pCurrentVoice->bIsPaused = pCurrentVoice->bIsMuted = FALSE;
pCurrentVoice->bIsFullSurround = (pCurrentVoice->pRealBitStream->ulDolbyMark == 'SUR2');
pCurrentVoice->bIsSurround = (pCurrentVoice->pRealBitStream->ulDolbyMark == 'SUR2') ||
(pCurrentVoice->pRealBitStream->ulDolbyMark == 'SUR1');
if (pCurrentVoice->bIsSurround) {
pCurrentVoice->pAssociatedVoice = pCurrentVoice + (kNumVoice+1);
pCurrentVoice->pAssociatedVoice->bIsPlaying = TRUE;
//pCurrentVoice->pAssociatedVoice->ucVolume = 127;
//pCurrentVoice->pAssociatedVoice->ucVolumeIndex = 0;
pCurrentVoice->pAssociatedVoice->bIsMuted = FALSE;
} else {
pCurrentVoice->pAssociatedVoice = NULL;
}
pCurrentVoice->ulPos = 0;
pCurrentVoice->ulFinalSize = pCurrentVoice->pRealBitStream->ulFinalSize ;
pCurrentVoice->bIsFinishing = FALSE;
pCurrentVoice->ulNumSampleBeforeEnd = 0;
pCurrentVoice->bIsFading = FALSE;
pCurrentVoice->iFadeVolume = 0;
pCurrentVoice->iFadeIncrement = 0;
return pCurrentVoice;
} else return NULL;
}
//-------------------------------------------------------------------------
// Description : Open a new voice from File
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
// Input : filename and number of channel
// Output : voice pointer
//-------------------------------------------------------------------------
// Creation date : 18/03/97 Author : Guillaume Michel
//-------------------------------------------------------------------------
// Modifications :
// Modification Date : Author :
//-------------------------------------------------------------------------
SND_tdstMPEGVoice* SND_fn_pSampleAllocateMPEGVoiceFile(char* pFileName, unsigned long ulOffset)
{
SND_tdstMPEGVoice* pCurrentVoice;
pCurrentVoice = &(MPEGvoices[2]);
if (!pCurrentVoice->bIsFree) {
SND_fn_vDisplayErrorEx(E_uwSndTooManySamples,"Too many MPEG streaming voices",SNDERR_DISPLAY_IF_WANTED);
return NULL;
}
//added by stepahen RONSE on 04/29/98
bSynthesisBufferCleaned=FALSE;
if (SND_fn_bOpenBitStreamFile(pCurrentVoice->pRealBitStream,pFileName,ulOffset)) {
// This voice will be used...
pCurrentVoice->bIsFree = FALSE;
pCurrentVoice->ucVolume = 127;
pCurrentVoice->ucCurrentVolume = 127;
pCurrentVoice->ucVolumeIndex = 0;
pCurrentVoice->bIsPaused = pCurrentVoice->bIsMuted = FALSE;
pCurrentVoice->bIsOneShot = TRUE;
pCurrentVoice->bIsFullSurround = (pCurrentVoice->pRealBitStream->ulDolbyMark == 'SUR2');
pCurrentVoice->bIsSurround = (pCurrentVoice->pRealBitStream->ulDolbyMark == 'SUR2') ||
(pCurrentVoice->pRealBitStream->ulDolbyMark == 'SUR1');
if (pCurrentVoice->bIsSurround) {
pCurrentVoice->pAssociatedVoice = pCurrentVoice + (kNumVoice+1);
pCurrentVoice->pAssociatedVoice->bIsPlaying = TRUE;
pCurrentVoice->pAssociatedVoice->ucVolume = 127;
pCurrentVoice->pAssociatedVoice->ucCurrentVolume = 127;
pCurrentVoice->pAssociatedVoice->ucVolumeIndex = 0;
pCurrentVoice->pAssociatedVoice->bIsMuted = FALSE;
} else {
pCurrentVoice->pAssociatedVoice = NULL;
}
pCurrentVoice->ulPos = 0;
pCurrentVoice->ulFinalSize = pCurrentVoice->pRealBitStream->ulFinalSize;
pCurrentVoice->bIsPlaying = TRUE;
pCurrentVoice->bIsFinishing = FALSE;
pCurrentVoice->ulNumSampleBeforeEnd = 0;
pCurrentVoice->bIsFading = FALSE;
pCurrentVoice->iFadeVolume = 0;
pCurrentVoice->iFadeIncrement = 0;
return pCurrentVoice;
} else return NULL;
}
//-------------------------------------------------------------------------
// Description : Open a new voice from memory
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
// Input : buffer pointer, buffer size, voice pointer and number of channel
// Output : voice pointer
//-------------------------------------------------------------------------
// Creation date : 18/03/97 Author : Guillaume Michel
//-------------------------------------------------------------------------
// Modifications :
// Modification Date : Author :
//-------------------------------------------------------------------------
SND_tdstMPEGVoice* SND_fn_pSampleAllocateMPEGVoiceMem(unsigned char* pBuffer, unsigned long ulSize)
{
SND_tdstMPEGVoice* pCurrentVoice;
pCurrentVoice = &(MPEGvoices[2]);
if (!pCurrentVoice->bIsFree) {
return NULL;
}
//added by stepahen RONSE on 04/29/98
bSynthesisBufferCleaned=FALSE;
if (SND_fn_bOpenBitStreamMem(pCurrentVoice->pRealBitStream,pBuffer,ulSize)) {
// This voice will be used...
pCurrentVoice->bIsFree = FALSE;
pCurrentVoice->bIsPlaying = TRUE;
pCurrentVoice->ucVolume = 127;
pCurrentVoice->ucCurrentVolume = 127;
pCurrentVoice->ucVolumeIndex = 0;
pCurrentVoice->bIsPaused = pCurrentVoice->bIsMuted = FALSE;
pCurrentVoice->bIsOneShot = TRUE;
pCurrentVoice->bIsFullSurround = (pCurrentVoice->pRealBitStream->ulDolbyMark == 'SUR2');
pCurrentVoice->bIsSurround = (pCurrentVoice->pRealBitStream->ulDolbyMark == 'SUR2') ||
(pCurrentVoice->pRealBitStream->ulDolbyMark == 'SUR1');
if (pCurrentVoice->bIsSurround) {
pCurrentVoice->pAssociatedVoice = pCurrentVoice + (kNumVoice+1);
pCurrentVoice->pAssociatedVoice->bIsPlaying = TRUE;
pCurrentVoice->pAssociatedVoice->ucVolume = 127;
pCurrentVoice->pAssociatedVoice->ucCurrentVolume = 127;
pCurrentVoice->pAssociatedVoice->ucVolumeIndex = 0;
pCurrentVoice->pAssociatedVoice->bIsMuted = FALSE;
} else {
pCurrentVoice->pAssociatedVoice = NULL;
}
pCurrentVoice->ulPos = 0;
pCurrentVoice->ulFinalSize = pCurrentVoice->pRealBitStream->ulFinalSize;
pCurrentVoice->bIsFinishing = FALSE;
pCurrentVoice->ulNumSampleBeforeEnd = 0;
pCurrentVoice->bIsFading = FALSE;
pCurrentVoice->iFadeVolume = 0;
pCurrentVoice->iFadeIncrement = 0;
return pCurrentVoice;
} else return NULL;
}
//-------------------------------------------------------------------------
// Description : close a voice
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
// Input : voice pointer
// Output : SndBool
//-------------------------------------------------------------------------
// Creation date : 18/03/97 Author : Guillaume Michel
//-------------------------------------------------------------------------
// Modifications :
// Modification Date : Author :
//-------------------------------------------------------------------------
SndBool SND_fn_bFreeMPEGVoice(SND_tdstMPEGVoice* pVoice)
{
snd_assert(pVoice);
snd_assert(pVoice->pRealBitStream == &pVoice->bitstream);
pVoice->bIsPlaying = FALSE;
pVoice->bIsPaused = FALSE;
SND_fn_bCloseBitStream(pVoice->pRealBitStream);
//pVoice->ucVolume = 0;
//pVoice->ucVolumeIndex = 0;
pVoice->bIsMuted = FALSE;
pVoice->ulPos = 0;
pVoice->ulFinalSize = 0;
pVoice->bIsOneShot = FALSE;
pVoice->bIsSurround = FALSE;
pVoice->pAssociatedVoice = NULL;
pVoice->bIsFinishing = FALSE;
pVoice->ulNumSampleBeforeEnd = 0;
// DO NOT CLEAR CALLBACK AND PARAM FIELDS !!!
if (pVoice == &MPEGvoices[2]) {
// one shot voices
iMiniFrameSample=12;
iIndexSample=3;
}
pVoice->bIsFree = TRUE;
return TRUE;
}
//-------------------------------------------------------------------------
// Description : read datas from the bit stream (Part I)
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
// Input : voice pointer
// Output : SndBool
//-------------------------------------------------------------------------
// Creation date : 18/03/97 Author : Guillaume Michel
//-------------------------------------------------------------------------
// Modifications :
// Modification Date : Author :
//-------------------------------------------------------------------------
SndBool SND_fn_bReadPartI(SND_tdstMPEGVoice* pVoice)
{
int i,j,k,l,m;
unsigned char *pucBitAlloc;
unsigned char *pucScaleFactorPattern;
unsigned char *pucScaleFactor;
SND_tdstBitStream *pbitstream;
unsigned short uwMode, uwExtMode, uwTmp;
unsigned char ucTmp;
snd_assert(pVoice);
pbitstream = pVoice->pRealBitStream;
if(SND_fn_bSeekSynch(pbitstream)) {
// We have found a synch word -> there is at least one frame
GETBITS(4,&uwMode,pbitstream);
uwExtMode = uwMode & 0x3,
uwMode >>= 2; // Tell us if we are in stereo mode, joint mode or mono mode
k = pVoice->ucNbChannel = (uwMode == kMono) ? 1 : 2;
l = pVoice->ucJointBound = (uwMode != kJointStereo) ? kSubBandLimit : iJointMode[uwExtMode];
// First READ bits allocations...
// before Joint boundary there are two bits allocation values
pucBitAlloc = pVoice->pucBitAlloc;
for (i = 0; i < l; i++) {
m = iNumBitPerChannel[i];
for (j = 0; j < k; j++) {
GETBITS((unsigned char)m,&uwTmp,pbitstream);
*pucBitAlloc++ = (unsigned char) uwTmp;
}
}
// after Joint boundary the same bit allocation value is used for left and right
for (i = l; i < kSubBandLimit; i++) {
GETBITS((unsigned char)iNumBitPerChannel[i],&uwTmp,pbitstream);
*pucBitAlloc++ = ucTmp = (unsigned char) uwTmp;
*pucBitAlloc++ = ucTmp;
}
// Now we can read scales factors...
pucBitAlloc = pVoice->pucBitAlloc;
pucScaleFactorPattern = pVoice->pucScaleFactorPattern;
for (i = 0; i < kSubBandLimit; i++) {
for(j = 0; j < k; j++) {
if(*pucBitAlloc++) {
GETBITS(2,&uwTmp,pbitstream);
*pucScaleFactorPattern = (unsigned char) uwTmp;
}
pucScaleFactorPattern++;
}
}
// Then we can read scale factor index
pucBitAlloc = pVoice->pucBitAlloc;
pucScaleFactorPattern = pVoice->pucScaleFactorPattern;
pucScaleFactor = pVoice->pucScaleFactor;
for (i = 0; i < kSubBandLimit; i++) {
for (j = 0; j < k; j++) {
if(*pucBitAlloc++) {
switch(*pucScaleFactorPattern++) {
case 0: // three different scale factors
GETBITS(6,&uwTmp,pbitstream);
*pucScaleFactor++ = (unsigned char) uwTmp;
GETBITS(6,&uwTmp,pbitstream);
*pucScaleFactor++ = (unsigned char) uwTmp;
GETBITS(6,&uwTmp,pbitstream);
*pucScaleFactor++ = (unsigned char) uwTmp;
break;
case 1:// two
GETBITS(6,&uwTmp,pbitstream);
*pucScaleFactor++ = ucTmp = (unsigned char) uwTmp;
*pucScaleFactor++ = ucTmp;
GETBITS(6,&uwTmp,pbitstream);
*pucScaleFactor++ = (unsigned char) uwTmp;
break;
case 3:// two
GETBITS(6,&uwTmp,pbitstream);
*pucScaleFactor++ = (unsigned char) uwTmp;
GETBITS(6,&uwTmp,pbitstream);
*pucScaleFactor++ = ucTmp = (unsigned char) uwTmp;
*pucScaleFactor++ = ucTmp;
break;
case 2:// one scale factor...
GETBITS(6,&uwTmp,pbitstream);
*pucScaleFactor++ = ucTmp = (unsigned char) uwTmp;
*pucScaleFactor++ = ucTmp;
*pucScaleFactor++ = ucTmp;
break;
default:
snd_assert(0); // should not happen
break;
}
} else {
pucScaleFactorPattern++;
pucScaleFactor += 3;
}
}
}
return TRUE;
} else return FALSE; // No more synch word -> EOF
}
//-------------------------------------------------------------------------
// Description : read datas from the bit stream (Part II)
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
// Input : voice pointer
// Output : SndBool
//-------------------------------------------------------------------------
// Creation date : 19/03/97 Author : Guillaume Michel
//-------------------------------------------------------------------------
// Modifications :
// Modification Date : Author :
//-------------------------------------------------------------------------
void SND_fn_vReadPartII(SND_tdstMPEGVoice* pVoice)
{
int i, j, jointboundary, k, ba, l, m;
unsigned short wTmp;
short *pwSample;
short *pwOldSample;
unsigned char *pucBitAlloc,ucl;
sb_alloc *pAllocTable;
sb_alloc *pAllocTable2;
SND_tdstBitStream *pBitStream;
jointboundary = pVoice->ucJointBound;
k = pVoice->ucNbChannel;
pBitStream = pVoice->pRealBitStream;
pwSample = pVoice->pwSample;
pucBitAlloc = pVoice->pucBitAlloc;
for (i = 0; i < kSubBandLimit; i++) {
pAllocTable2 = &AllocationTable[i][0];
for (j = 0; j < ((i < jointboundary) ? k : 1); j++) {
if ( ba = (*pucBitAlloc++)) {
// There are samples to read
ba--;
pAllocTable = pAllocTable2 + ba;
l = pAllocTable->bits;
ucl = (unsigned char) l;
if (pAllocTable->group == 3) {
// No Grouping...
GETBITS(ucl,(unsigned short*)(pwSample++),pBitStream);
GETBITS(ucl,(unsigned short*)(pwSample++),pBitStream);
GETBITS(ucl,(unsigned short*)(pwSample++),pBitStream);
} else {
// Grouping...
m = pAllocTable->steps;
GETBITS(ucl,&wTmp,pBitStream);
// degroup...
#if defined(__WATCOMC__) && (__WATCOMC__<1100)
*pwSample++ = wTmp % m;
wTmp /= m;
*pwSample++ = wTmp % m;
wTmp /= m;
*pwSample++ = wTmp;
#else
_asm {
xor eax,eax
mov esi, pwSample
xor edx, edx
mov ax, wTmp
div m
mov word ptr [esi], dx
xor edx, edx
div m
mov word ptr [esi + 2], dx
mov word ptr [esi + 4], ax
add esi, 6
mov pwSample,esi
}
#endif //Watcom
}
} else {
*pwSample++ = 0;
*pwSample++ = 0;
*pwSample++ = 0;
}
}
if( (k == 2) && (i >= jointboundary)) {
pwOldSample = pwSample - 3; // last three sample read
*pwSample++ = *pwOldSample++;
*pwSample++ = *pwOldSample++;
*pwSample++ = *pwOldSample++;
pucBitAlloc++;
}
}
}
SndBool SND_fn_bRead(SND_tdstMPEGVoice* pVoice)
{
if ((pVoice->bIsPlaying)&&(!pVoice->bIsPaused)) {
if (SND_fn_bReadPartI(pVoice)) {
SND_fn_vEvaluateSCF(pVoice);
} else {
pVoice->bIsPlaying = FALSE;
if (pVoice == &MPEGvoices[2]) {
// voix offs
pVoice->bIsFinishing = TRUE;
pVoice->ulNumSampleBeforeEnd = 32*kFrameSize;
}
}
}
return pVoice->bIsPlaying;
}
SndBool SND_fn_bFinishRead(SND_tdstMPEGVoice* pVoice)
{
int j;
if ((pVoice->bIsPlaying)&&(!pVoice->bIsPaused)) {
for(j =0; j < 12; j++) {
SND_fn_vReadPartII(pVoice);
if (!((pVoice->ucVolume==0) || pVoice->bIsMuted))
SND_fn_vDequantizeSample(pVoice,j);
}
}
return TRUE;
}
SndBool SND_fn_bSwitchPart()
{
unsigned long ulPar;
SndBool bPartIsFading;
SND_td_pfn_vSoundCallback pcb;
SND_tdstMPEGVoice* pOldVoice = pSwapVoice[0];
SND_tdstMPEGVoice* pNewVoice = pSwapVoice[1];
bPartIsFading=pOldVoice->bIsFading;
pcb = pOldVoice->pfnCallBack;
ulPar = pOldVoice->ulParam;
pOldVoice->bIsPlaying = FALSE;
// TRY WITH NEXT ONE...
if (pSwapVoice[1]->bIsPlaying)
{
// OutputDebugString("Switch part called, ");
// WE MUST TRY VOICE TWO
// swap the voices...
pSwapVoice[0] = pNewVoice;
pSwapVoice[1] = pOldVoice;
if (bPartIsFading)
{// copy fade params from previous voice to new one:
pNewVoice->bIsFading = TRUE;
pNewVoice->iFadeVolume = pOldVoice->iFadeVolume;
pNewVoice->iFadeIncrement = pOldVoice->iFadeIncrement;
}
// We either launch a transition because of a forecoming transition with fade,
// in which case we disable the callback, or we call the callback as usual:
if (SND_g_uFadeRes.pstPtr!=NULL)
{
// OutputDebugString("Calling set transition \n");
SND_fn_bSetNextTransitionMPEG(0,SND_g_uFadeRes);
SND_g_uFadeRes.pstPtr=NULL;
}
else if (pcb)
{
// OutputDebugString("Calling callback \n");
pcb(ulPar);
}
else
pcb=pcb;
return TRUE;
} else
{
return FALSE;
}
}
//-------------------------------------------------------------------------
// Description: do the mix to fill the client buffer
// in the case of SINGLE CHANNEL, if one voice can't fill the client buffer
// we try with the next voice...
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
// Input : buffer pointer and size in samples
// Output : SndBool
//-------------------------------------------------------------------------
// Creation date : 20/03/97 Author : Guillaume Michel
//-------------------------------------------------------------------------
// Modifications :
// Modification Date : Author :
//-------------------------------------------------------------------------
SndBool SND_fn_bFillBufferTwice(short* pwBuffer, unsigned long ulSize)
{
unsigned long ulNbSample;
int iResultDecoder = 0;
int iMaxFrameToDo;
SndBool bVoiceEnded;//TRUE si une voie s'est arret<65>e pendant le mixage->SWAP?
while ( ulSize ) {
//on regarde si il y a des r<>sidus <20> caser...
/*
* Currently we get previous remain decompress data size
*/
ulNbSample = pwOutBufferEnd2 - pwOutBufferPos;
ulNbSample >>= 1;
if (ulNbSample) {
// il y a encore des restes
if (ulSize <= ulNbSample) {
// il y en a assez...
memcpy(pwBuffer,pwOutBufferPos,(ulSize<<1)*sizeof(short));
pwOutBufferPos += (ulSize<<1);
return TRUE;
} else {
memcpy(pwBuffer,pwOutBufferPos,(ulNbSample<<1)*sizeof(short));
pwOutBufferPos = pwOutBufferEnd2;
pwBuffer += (ulNbSample<<1);
ulSize -= ulNbSample;
}
}
if (ulSize < kNumChannel) {
// on doit d<>coder dans le buffer temporaire
bVoiceEnded=SND_fn_bGetOneFrame(pwOutBuffer,1,&iResultDecoder);
if (bVoiceEnded || (iResultDecoder != kNumChannel)) {
pwOutBufferEnd2 = pwOutBuffer +(iResultDecoder<<1);
if (bSwitchPart) {
// On swapp: il y a donc quelque chose dans le buffer temporiare
if(SND_fn_bSwitchPart()) {
// On peut swapper de part en part
if (ulSize >= (unsigned long)iResultDecoder) {
// on n'a pas d<>cod<6F> assez...
memcpy(pwBuffer,pwOutBuffer,(iResultDecoder<<1)*sizeof(short));
pwOutBufferPos = pwOutBufferEnd2;
ulSize -= iResultDecoder;
pwBuffer += (iResultDecoder<<1);
} else {
// on a d<>cod<6F> assez...
memcpy(pwBuffer,pwOutBuffer,(ulSize<<1)*sizeof(short));
pwOutBufferPos = pwOutBuffer + (ulSize<<1);
return TRUE;
}
} else {
// On ne peut pas swapper
if (ulSize >= (unsigned long)iResultDecoder) {
// on n'a pas d<>cod<6F> assez...
memcpy(pwBuffer,pwOutBuffer,(iResultDecoder<<1)*sizeof(short));
pwOutBufferPos = pwOutBufferEnd2;
ulSize -= iResultDecoder;
memset(pwBuffer+(iResultDecoder<<1),0,(ulSize<<1)*sizeof(short));
} else {
// on a d<>cod<6F> assez...
memcpy(pwBuffer,pwOutBuffer,(ulSize<<1)*sizeof(short));
pwOutBufferPos = pwOutBuffer + (ulSize<<1);
ulSize = 0;
}
//added by stephane RONSe on 04/29/98
if (!bSynthesisBufferCleaned)
{
fn_vCleanSynthesisBuffer();
bSynthesisBufferCleaned=TRUE;
}
return FALSE;
}
} else {
// Pas de switch -> arr<72>t normal -> pas de d<>codage
pwOutBufferPos = pwOutBufferEnd2;
memset(pwBuffer,0, (ulSize<<1)*sizeof(short));
//added by stephane RONSe on 04/29/98
if (!bSynthesisBufferCleaned)
{
fn_vCleanSynthesisBuffer();
bSynthesisBufferCleaned=TRUE;
}
return FALSE;
}
} else {
// tout est ok... on continu
memcpy(pwBuffer,pwOutBuffer,(ulSize<<1)*sizeof(short));
pwBuffer += (ulSize<<1);
pwOutBufferPos = pwOutBuffer + (ulSize<<1);
pwOutBufferEnd2 = pwOutBuffer +(kNumChannel<<1);
ulSize = 0;
// normalement cela doit <20>tre termin<69>...
}
} else {
iMaxFrameToDo = ulSize>>5;
// on peut d<>coder directement au bon endroit
bVoiceEnded=SND_fn_bGetOneFrame(pwBuffer,iMaxFrameToDo,&iResultDecoder);
if (bVoiceEnded || (iResultDecoder != (iMaxFrameToDo<<5))) {
if (bSwitchPart) {
if(SND_fn_bSwitchPart()) {
pwBuffer += (iResultDecoder<<1);
ulSize -= iResultDecoder;
} else {
memset(pwBuffer+(iResultDecoder<<1),0, ((ulSize-iResultDecoder)<<1)*sizeof(short));
//added by stephane RONSe on 04/29/98
if (!bSynthesisBufferCleaned)
{
fn_vCleanSynthesisBuffer();
bSynthesisBufferCleaned=TRUE;
}
return FALSE;
}
} else {
memset(pwBuffer,0, (ulSize<<1)*sizeof(short));
//added by stephane RONSe on 04/29/98
if (!bSynthesisBufferCleaned)
{
fn_vCleanSynthesisBuffer();
bSynthesisBufferCleaned=TRUE;
}
return FALSE;
}
} else {
// tout est ok... on continu
ulSize -= iResultDecoder;
pwBuffer += (iResultDecoder<<1);
}
}
}
return TRUE;
}
void WINAPI SND_fn_vRefreshMPEG(long idBuffer,unsigned long idSample, unsigned long nbSample, void* pvBuffer)
{
bInMPEGDecomp = TRUE; //MUTEX
SND_fn_bFillBufferTwice((short*)pvBuffer,nbSample);
//memcpy(pBigInBuffer,pvBuffer,nbSample*2*2);
//pBigInBuffer+=2*nbSample;
bInMPEGDecomp = FALSE; // MUTEX
}
void SND_fnvStopAllVoicesMPEGTheme()
{
// Stop the two voices associated with theme player...
// both voices are stopped...
pSwapVoice[1]->bIsPlaying = pSwapVoice[0]->bIsPlaying = FALSE;
pSwapVoice[1]->bIsPaused = pSwapVoice[0]->bIsPaused = FALSE;
// wait for end of the current frame decompression
// this function and GetOneFrame MUST BE IN TWO DIFFERENT THREADS !!!
while(bInMPEGDecomp){
Sleep(30);
}
iMiniFrameTheme=12;
iIndexTheme=3;
SND_fn_bFreeMPEGVoice(pSwapVoice[0]);
SND_fn_bFreeMPEGVoice(pSwapVoice[1]);
}