gssound.cpp

来自「网络泡泡被.net管理」· C++ 代码 · 共 364 行

CPP
364
字号
// GsSound.cpp: implementation of the CGsSound class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "GSLib_Internal.h"
#include <mmsystem.h>
#include <dxerr8.h>
#include <dsound.h>

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CGsSound::CGsSound(CGsEngine*	pEngine)
{
	m_pEngine		= pEngine;
	m_pDSB		= NULL;
	m_pDSB_3d	= NULL;
	m_flag		= 0;

	m_key_source	= "";

    ZeroMemory( &m_dsbd, sizeof(DSBUFFERDESC) );

}
VOID CGsSound::Cleanup()
{
	m_flag		= 0;
	m_key_source	= "";
	SAFE_RELEASE(m_pDSB);
	SAFE_RELEASE(m_pDSB_3d);
    ZeroMemory( &m_dsbd, sizeof(DSBUFFERDESC) );
}

CGsSound::~CGsSound()
{
	std::map<KEY, std::set<CGsSound*> >::iterator it_sm = m_pEngine->m_sound_cache.find(m_key_source);
	std::set<CGsSound*>::iterator it_ss;
	if(it_sm!=m_pEngine->m_sound_cache.end())
	{
		it_ss	= it_sm->second.find(this);
		if(it_ss!=it_sm->second.end())
		{
			it_sm->second.erase(it_ss);
		}
		if(it_sm->second.size()==0)
		{
			m_pEngine->m_sound_cache.erase(it_sm);
		}
	}
	Cleanup();
}

VOID CGsSound::Set3D(float x, float y, float z)
{
	if(m_pDSB_3d)
		m_pDSB_3d->SetPosition(x,y,z,DS3D_DEFERRED);
}

HRESULT CGsSound::Play()
{
	if(m_pDSB==NULL)
		return S_OK;
    return m_pDSB->Play( 0, 0, 0);//DSBPLAY_LOOPING );
}
HRESULT CGsSound::PlayLoop()
{
	if(m_pDSB==NULL)
		return S_OK;
    return m_pDSB->Play( 0, 0, DSBPLAY_LOOPING );
}

HRESULT CGsSound::Reset()
{
	if(m_pDSB==NULL)
		return S_OK;
	return m_pDSB->SetCurrentPosition( 0 );
}

HRESULT CGsSound::SetPos(float pos)
{
	if(m_pDSB==NULL)
		return S_OK;
	return m_pDSB->SetCurrentPosition( ((DWORD)(m_size*pos))&m_size );
}

HRESULT CGsSound::Stop()
{
	if(m_pDSB==NULL)
		return S_OK;
	return m_pDSB->Stop();
}


VOID CGsSound::SetSound(char *szFile)
{
	if(szFile==NULL)
		return;

}

#pragma pack(push, 1)
struct t_dsb_file_head
{
	char			str_version[16];
};
#pragma pack(pop)

HRESULT CGsSound::Import(const char *szFile)
{
	GSFBUF	gsbuf;
//	if(NULL!=m_pEngine->GetSourcePtr()->FindSource(KEY(szFile), gsbuf))
//	{
//		return Import(gsbuf);
//	}
	if((gsbuf.p_fstream	= fopen(szFile, "rb"))==NULL)
		return E_FAIL;
	gsbuf.pos_begin	= 0;
	gsbuf.file_size	= 0;
	if(FAILED(Import(gsbuf)))
	{
		fclose(gsbuf.p_fstream);
		return CreateFromWaveFile(szFile);
	}
	fclose(gsbuf.p_fstream);
	return S_OK;
}

HRESULT CGsSound::Import(GSFBUF &gsbuf)
{
	HRESULT hr;
	t_dsb_file_head head;
	ZeroMemory(&head, sizeof(head));
	fseek(gsbuf.p_fstream, gsbuf.pos_begin, SEEK_SET);//>seekg(gsbuf.posBegin);
//	gsbuf.pfstream->read((char*)&head, sizeof(head));
	fread(&head, sizeof(head), 1, gsbuf.p_fstream);
	if(strstr(head.str_version, "GSSB")!=head.str_version)
		return E_FAIL;
//	gsbuf.pfstream->read((char*)&m_dsbd, sizeof(m_dsbd));
	fread(&m_dsbd, sizeof(m_dsbd), 1, gsbuf.p_fstream);
	hr	= m_pEngine->GetDirectSound()->CreateSoundBuffer( &m_dsbd, &m_pDSB, NULL );
	if(FAILED(hr))
		return hr;

    VOID*   pDSLockedBuffer      = NULL; // Pointer to locked buffer memory
    DWORD   dwDSLockedBufferSize = 0;    // Size of the locked DirectSound buffer

    if( FAILED( hr = m_pDSB->Lock( 0, m_dsbd.dwBufferBytes, 
                                 &pDSLockedBuffer, &dwDSLockedBufferSize, 
                                 NULL, NULL, 0L ) ) )
        return hr;//DXTRACE_ERR( TEXT("Lock"), hr );

// 	gsbuf.pfstream->read((char*)pDSLockedBuffer, m_dsbd.dwBufferBytes);
	if(m_dsbd.dwBufferBytes!=fread(pDSLockedBuffer, 1, m_dsbd.dwBufferBytes, gsbuf.p_fstream))
	{
	}
    m_pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 );

	m_pDSB->QueryInterface( IID_IDirectSound3DBuffer, 
								(VOID**)&m_pDSB_3d );

	return S_OK;
}

HRESULT CGsSound::CreateFromWaveFile(const char *szFile)
{
	HRESULT hr;
	t_wave_file	wave_file;
    wave_file.Open( (char*)szFile, NULL, WAVEFILE_READ );
    if( wave_file.GetSize() == 0 )
    {
        // Wave is blank, so don't create it.
        return E_FAIL;
    }

    // Make the DirectSound buffer the same size as the wav file
    DWORD dwDSBufferSize = wave_file.GetSize();


    // Create the direct sound buffer, and only request the flags needed
    // since each requires some overhead and limits if the buffer can 
    // be hardware accelerated
    ZeroMemory( &m_dsbd, sizeof(DSBUFFERDESC) );
    m_dsbd.dwSize          = sizeof(DSBUFFERDESC);
    m_dsbd.dwBufferBytes   = dwDSBufferSize;
	if(wave_file.m_pwfx->nChannels > 1 ||  wave_file.m_pwfx->wFormatTag != WAVE_FORMAT_PCM )
	{
		m_dsbd.dwFlags         = 0;
		m_dsbd.guid3DAlgorithm = GUID_NULL;
	}
	else
	{
		m_dsbd.dwFlags         = DSBCAPS_CTRL3D;
		m_dsbd.guid3DAlgorithm = DS3DALG_HRTF_FULL;
	}
    m_dsbd.lpwfxFormat     = wave_file.m_pwfx;

    // DirectSound is only guarenteed to play PCM data.  Other
    // formats may or may not work depending the sound card driver.
    hr	= m_pEngine->GetDirectSound()->CreateSoundBuffer( &m_dsbd, &m_pDSB, NULL );
	if(FAILED(hr))
		return hr;

    VOID*   pDSLockedBuffer      = NULL; // Pointer to locked buffer memory
    DWORD   dwDSLockedBufferSize = 0;    // Size of the locked DirectSound buffer
    DWORD   dwWavDataRead        = 0;    // Amount of data read from the wav file 
    if( FAILED( hr = m_pDSB->Lock( 0, m_dsbd.dwBufferBytes, 
                                 &pDSLockedBuffer, &dwDSLockedBufferSize, 
                                 NULL, NULL, 0L ) ) )
        return hr;//DXTRACE_ERR( TEXT("Lock"), hr );

    // Reset the wave file to the beginning 
    wave_file.ResetFile();

    if( FAILED( hr = wave_file.Read( (BYTE*) pDSLockedBuffer,
                                        dwDSLockedBufferSize, 
                                        &dwWavDataRead ) ) )           
        return hr;//DXTRACE_ERR( TEXT("Read"), hr );

    if( dwWavDataRead == 0 )
    {
        // Wav is blank, so just fill with silence
        FillMemory( (BYTE*) pDSLockedBuffer, 
                    dwDSLockedBufferSize, 
                    (BYTE)(wave_file.m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) );
    }
    else if( dwWavDataRead < dwDSLockedBufferSize )
    {
        // If the wav file was smaller than the DirectSound buffer, 
        // we need to fill the remainder of the buffer with data 
		/*
        if( bRepeatWavIfBufferLarger )
        {       
            // Reset the file and fill the buffer with wav data
            DWORD dwReadSoFar = dwWavDataRead;    // From previous call above.
            while( dwReadSoFar < dwDSLockedBufferSize )
            {  
                // This will keep reading in until the buffer is full 
                // for very short files
                if( FAILED( hr = wave_file.ResetFile() ) )
                    return hr;//DXTRACE_ERR( TEXT("ResetFile"), hr );

                hr = wave_file.Read( (BYTE*)pDSLockedBuffer + dwReadSoFar,
                                        dwDSLockedBufferSize - dwReadSoFar,
                                        &dwWavDataRead );
                if( FAILED(hr) )
                    return hr;//DXTRACE_ERR( TEXT("Read"), hr );

                dwReadSoFar += dwWavDataRead;
            } 
        }
        else*/
        {
            // Don't repeat the wav file, just fill in silence 
            FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead, 
                        dwDSLockedBufferSize - dwWavDataRead, 
                        (BYTE)(wave_file.m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) );
        }
    }


    m_pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 );

	m_pDSB->QueryInterface( IID_IDirectSound3DBuffer, 
								(VOID**)&m_pDSB_3d );
	return S_OK;
}

DWORD CGsSound::Export(const char *szFile)
{
//	fstream fbuf;
//	fbuf.open(szFile, ios::in | ios::out | ios::binary | ios::trunc);
//	if(!fbuf)
//		return 0;
	GSFBUF gsbuf;
	if((gsbuf.p_fstream	= fopen(szFile, "wb"))==NULL)
		return 0;
	
	gsbuf.pos_begin	= 0;
	gsbuf.file_size	= 0;

	DWORD ret	= Export(gsbuf);

	fclose(gsbuf.p_fstream);
	return ret;
}

DWORD CGsSound::Export(GSFBUF &gsbuf)
{
	DWORD	dwWrite = 0;
	t_dsb_file_head head;
	ZeroMemory(&head, sizeof(head));
	strcpy(head.str_version, "GSSB2003a");
//	gsbuf.pfstream->seekg(gsbuf.posBegin);
	fseek(gsbuf.p_fstream, gsbuf.pos_begin, SEEK_SET );
//	gsbuf.pfstream->write((char*)&head, sizeof(head));
	dwWrite+=fwrite(&head, sizeof(head), 1, gsbuf.p_fstream);
//	gsbuf.pfstream->write((char*)&m_dsbd, sizeof(m_dsbd));
	dwWrite+=fwrite(&m_dsbd, sizeof(m_dsbd), 1, gsbuf.p_fstream);
    VOID*   pDSLockedBuffer      = NULL; // Pointer to locked buffer memory
    DWORD   dwDSLockedBufferSize = 0;    // Size of the locked DirectSound buffer

    if( FAILED( m_pDSB->Lock( 0, m_dsbd.dwBufferBytes, 
                                 &pDSLockedBuffer, &dwDSLockedBufferSize, 
                                 NULL, NULL, 0L ) ) )
        return 0;//DXTRACE_ERR( TEXT("Lock"), hr );

//	gsbuf.pfstream->write((char*)pDSLockedBuffer, m_dsbd.dwBufferBytes);
	dwWrite+=fwrite(pDSLockedBuffer, 1, m_dsbd.dwBufferBytes, gsbuf.p_fstream);

    m_pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 );

	return dwWrite;
}

BOOL CGsSound::IsPlaying()
{
	if(!m_pDSB)	
		return false;
	DWORD dwStatus;
	m_pDSB->GetStatus( &dwStatus );
	return (( dwStatus & DSBSTATUS_PLAYING ) != 0);
}

VOID CGsSound::SetReserve()
{
	m_flag	|= GS_SOUND_RESERVE;
}

BOOL CGsSound::IsFree()
{
	if((m_flag & GS_SOUND_RESERVE)==GS_SOUND_RESERVE)
		return false;
	return !IsPlaying();
}



BOOL CGsSound::SetStreamSource(const char *strSource)
{
	Cleanup();
	m_key_source	= strSource;

	GSFILE_INFO* file_info = m_pEngine->FindSource(strSource);
	if(file_info)
	{
		switch(file_info->fft)
		{
		case	GSF_WAV:
			if(FAILED(Import(file_info->strFile)))
				return FALSE;
			break;
		default:
			return FALSE;
		}
	}
	else
	{
		if(FAILED(Import(strSource)))
			return FALSE;
	}
	return TRUE;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?