/* // ================================================================ // 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 écrase la voie secondaire (impératif thè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 écrase la voie secondaire (impératif thè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ée pendant le mixage->SWAP? while ( ulSize ) { //on regarde si il y a des résidus à 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é assez... memcpy(pwBuffer,pwOutBuffer,(iResultDecoder<<1)*sizeof(short)); pwOutBufferPos = pwOutBufferEnd2; ulSize -= iResultDecoder; pwBuffer += (iResultDecoder<<1); } else { // on a décodé 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é 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é 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ê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 être terminé... } } 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]); }