📄 sbuffer.cpp
字号:
// SBuffer.cpp: implementation of the CSBuffer class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSBuffer::CSBuffer()
{
m_pDS = NULL;
m_lpDSB = NULL;
m_Filename = NULL;
m_Current = 0;
m_dwLastUseTime = 0;
m_nBuffers = 1;
m_3d = FALSE;
m_lp3dBuffer = NULL;
m_Streamed = FALSE;
m_sFile=NULL;
// m_pbUsingBuffer = NULL;
m_ID=0;
}
CSBuffer::~CSBuffer()
{
Stop();
Release();
}
VOID CSBuffer::Release(VOID)
{
DWORD Status=0;
if(m_ID!=0)
{
if( m_lpDSB )
{
for(int i = m_nBuffers-1; i >-1 ; i--)
{
if(SUCCEEDED(m_lpDSB[i]->GetStatus(&Status)))
{
if(Status&DSBSTATUS_PLAYING)
m_lpDSB[i]->Stop();
HRESULT hResult = m_lpDSB[i]->Release();
// delete *m_lpDSB[i];
m_lpDSB[i] = NULL;
}
}
DELETEARRAY(m_lpDSB);
m_lpDSB = NULL;
}
if( m_lp3dBuffer )
{
for(int i = 0; i < m_nBuffers; i++) SAFE_RELEASE(m_lp3dBuffer[i]);
DELETEARRAY(m_lp3dBuffer);
}
if( m_Streamed && m_sStop )
{
if( m_sFile )
{
fclose(m_sFile);
m_sFile=NULL;
}
}
m_pDS = NULL;
m_ID=0;
}
}
HRESULT CSBuffer::Load(CSound *pDS, const char *Filename, int Num)
{
CHAR szFname[MAX_PATH];
// Check the Parameters
if( Filename == NULL ) return DSERR_INVALIDPARAM;
HRESULT rval=DSERR_GENERIC;
FILE *fptr;
strcpy(szFname,"Sound\\");
strcat(szFname,Filename);
fptr = fopen( szFname, "rb" );
if( fptr )
{
if(m_Streamed)
{
m_sStop=FALSE;
m_sFile=fptr;
}
rval = Load( pDS, 0, fptr, Num );
if(!m_Streamed) fclose( fptr );
m_Filename = Filename;
}
return rval;
}
HRESULT CSBuffer::Load(CSound* pDS, LONG lSize, CHAR* lpCache, int Num)
{
HRESULT rval;
rval = Extract(pDS, lSize, lpCache, Num);
return rval;
}
HRESULT CSBuffer::Load(CSound *pDS, LONG lSize, FILE *fptr, int Num)
{
HRESULT rval;
CHAR* lpCache;
int length, save;
// Release all allocated Memory, befor continue
// m_nBuffers = Num;
Release( );
length = lSize;
// If lSize equals zero get the size of the file.
if(length == 0)
{
// Save the pointer location
save = ftell(fptr);
if(ferror(fptr))
return NULL;
// Seek to end of file
fseek(fptr, 0, SEEK_END);
if(ferror(fptr))
return NULL;
// Get the size of the file
length = ftell(fptr);
if(ferror(fptr))
return NULL;
// Seek back to save position
fseek(fptr, save, SEEK_SET);
if(ferror(fptr))
return NULL;
}
// Cache the whole file in memory
// Allocate memory to hold the data
lpCache = new CHAR[length];
if(lpCache == NULL)
return NULL;
// Read in the data
fread(lpCache, 1, length, fptr);
if(ferror(fptr))
{
delete [] lpCache;
return NULL;
}
// Load it from memory.
rval = Extract(pDS, length, lpCache, Num);
// Delete the cache
delete [] lpCache;
return rval;
}
HRESULT CSBuffer::Extract(CSound *pDS, LONG lSize, char *ptr, int Num)
{
HRESULT rval;
// Release all memory, befor continue
Release();
// Check the Parameters
if( ptr == NULL ) return DSERR_INVALIDPARAM;
if( pDS == NULL ) return DSERR_INVALIDPARAM;
if( pDS->GetDS() == NULL ) return DSERR_UNINITIALIZED;
if( m_Streamed ) return DSERR_INVALIDPARAM;
if( Num<1 ) Num = 1;
m_pDS = pDS;
m_nBuffers = Num;
m_Filename = NULL;
if( strncmp( ptr, "RIFF", 4 ) || strncmp( ptr+8, "WAVE", 4 ) )
return DSERR_BADFORMAT;
DWORD hSize = *(DWORD*)(ptr+16);
LPWAVEFORMATEX lpWav = (LPWAVEFORMATEX)(ptr+20);
// skip all "fact" and search for the data
// the fact stores the uncompressed filesize
DWORD dSize = 0;
ptr += 20 + hSize;
do
{
if( dSize ) ptr += dSize + 8;
dSize = *(DWORD*)(ptr+4);
} while( !strncmp( ptr, "fact", 4 ) );
ptr += 8;
// Is it compressed or a normal PCM Wave File
if( lpWav->wFormatTag == WAVE_FORMAT_PCM )
{
// Create the sound buffer for the wave file
rval = CreateSoundBuffer( dSize, (PCMWAVEFORMAT*)lpWav, Num );
if(FAILED(rval)) return rval;
// Read the data for the wave file into the sound buffer
rval = ReadDataFromMemory( ptr, dSize );
if(FAILED(rval)) return rval;
}
// Duplicate Buffers
for( int i = 1; i < m_nBuffers; i++ )
{
rval = m_pDS->GetDS()->DuplicateSoundBuffer(m_lpDSB[0], &m_lpDSB[i]);
if(FAILED(rval)) return rval;
if( m_3d )
{
rval = m_lpDSB[0]->QueryInterface(IID_IDirectSound3DBuffer, (LPVOID *)&m_lp3dBuffer[i]);
if(FAILED(rval)) return rval;
}
}
return DS_OK;
//return DSERR_UNSUPPORTED;
}
HRESULT CSBuffer::CreateSoundBuffer(DWORD dwBufSize, PCMWAVEFORMAT *pcmwf, int Num)
{
HRESULT rval;
// Create Space for Soundbuffer Pointers
m_lpDSB = new LPDIRECTSOUNDBUFFER[Num];
if( m_lpDSB == NULL ) return DSERR_OUTOFMEMORY;
ZeroMemory( m_lpDSB, sizeof( LPDIRECTSOUNDBUFFER )*Num );
if( m_3d )
{
m_lp3dBuffer = new LPDIRECTSOUND3DBUFFER[Num];
if( m_lp3dBuffer == NULL ) return DSERR_OUTOFMEMORY;
ZeroMemory( m_lp3dBuffer, sizeof( LPDIRECTSOUNDBUFFER )*Num );
}
DSBUFFERDESC dsbdesc;
// Set up DSBUFFERDESC structure.
ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC));
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwBufferBytes = dwBufSize;
dsbdesc.lpwfxFormat = (LPWAVEFORMATEX)pcmwf;
if( m_Streamed ) dsbdesc.dwFlags=DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRLPOSITIONNOTIFY;
else if( m_3d ) dsbdesc.dwFlags=DSBCAPS_CTRL3D|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_MUTE3DATMAXDISTANCE|DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME;
else dsbdesc.dwFlags=DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_STATIC;
rval=m_pDS->GetDS()->CreateSoundBuffer(&dsbdesc, &m_lpDSB[0], NULL);
if( FAILED(rval) ) return rval;
if( m_3d )
{
rval=m_lpDSB[0]->QueryInterface(IID_IDirectSound3DBuffer, (LPVOID *)&m_lp3dBuffer[0]);
if(FAILED(rval)) return rval;
}
return DS_OK;
}
HRESULT CSBuffer::ReadDataFromMemory(char *ptr, DWORD dwSize)
{
// Lock data in buffer for writing
LPVOID pData1, pData2;
DWORD dwData1Size, dwData2Size;
HRESULT rval;
rval = m_lpDSB[0]->Lock(0, 0, &pData1, &dwData1Size, &pData2, &dwData2Size, DSBLOCK_ENTIREBUFFER);
if(FAILED(rval)) return rval;
// Read in data(on dx3 read in first chunk)
if(dwData1Size>0)
{
memcpy(pData1, ptr, dwData1Size);
ptr+=dwData1Size;
}
// Read in second chunk if necessary
if(dwData2Size>0) memcpy(pData2, ptr, dwData2Size);
// Unlock data in buffer
rval = m_lpDSB[0]->Unlock(pData1, dwData1Size, pData2, dwData2Size);
if(FAILED(rval)) return rval;
return DS_OK;
}
HRESULT CSBuffer::Play( DWORD dwFlags )
{
HRESULT rval;
LPDIRECTSOUNDBUFFER Buffer = NULL;
if( m_pDS==NULL ) return DSERR_UNINITIALIZED;
if( m_pDS->GetSoundOn( ) ) return DS_OK;
Buffer = GetFreeBuffer();
if( Buffer==NULL ) return DSERR_ALLOCATED;
if(m_Streamed)
{
m_sLoop=dwFlags;
dwFlags=DSBPLAY_LOOPING;
}
m_dwLastUseTime = timeGetTime();
rval=Buffer->Play(0, 0, dwFlags);
if(FAILED(rval)) return rval;
return DS_OK;
}
LPDIRECTSOUNDBUFFER CSBuffer::GetFreeBuffer(VOID)
{
DWORD Status;
HRESULT rval;
LPDIRECTSOUNDBUFFER Buffer;
Status = 0;
nBufferIdx = MAX_DUPLE_COUNT;
if(m_lpDSB==NULL) return NULL;
if(m_ID!=0)
{
Buffer=m_lpDSB[m_Current];
rval = Buffer->GetStatus(&Status);
nBufferIdx = m_Current;
if(FAILED(rval)) Status = 0;
if((Status & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING)
{
if(m_nBuffers > 1)
{
if (++m_Current >= m_nBuffers)
{
m_Current = 0;
}
Buffer = m_lpDSB[m_Current];
rval = Buffer->GetStatus(&Status);
nBufferIdx = m_Current;
if(SUCCEEDED(rval) && (Status & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING)
{
// Play吝捞搁 家府甫 肛眠绊 贸澜栏肺 倒赴促.
/* Buffer->Stop();
Buffer->SetCurrentPosition(0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -