⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 infones_sound_win.cpp

📁 游戏模拟器InfoNes的原代码。有兴趣的可以将它移植到linux下
💻 CPP
字号:
/*===================================================================*/
/*                                                                   */
/*  InfoNES_Sound_Win.cpp : Implementation of DIRSOUND Class         */
/*                                                                   */
/*  2000/05/18  InfoNES Project                                      */
/*                                                                   */
/*===================================================================*/

/*-------------------------------------------------------------------*/
/*  Include files                                                    */
/*-------------------------------------------------------------------*/

#include <windows.h>
#include <mmsystem.h>
#include "dsound.h"
#include "InfoNES_Sound_Win.h"
#include "../InfoNES_System.h"

/*-------------------------------------------------------------------*/
/*  Constructor                                                      */
/*-------------------------------------------------------------------*/
DIRSOUND::DIRSOUND(HWND hwnd)
{
	DWORD ret;
	WORD x;

  // init variables
  iCnt = Loops * 3 / 4;

	for ( x = 0;x < ds_NUMCHANNELS; x++ )
	{
		lpdsb[x] = NULL;
	}

  // init DirectSound
	ret = DirectSoundCreate(NULL, &lpdirsnd, NULL);

	if (ret != DS_OK)
	{
    InfoNES_MessageBox( "Sound Card is needed to execute this application." );
		exit(-1);
	}

  // set cooperative level
#if 1
  ret = lpdirsnd->SetCooperativeLevel(hwnd, DSSCL_PRIORITY);
#else
  ret = lpdirsnd->SetCooperativeLevel( hwnd, DSSCL_NORMAL );
#endif

	if ( ret != DS_OK )
	{
    InfoNES_MessageBox( "SetCooperativeLevel() Failed." );
		exit(-1);
	}
}

/*-------------------------------------------------------------------*/
/*  Destructor                                                       */
/*-------------------------------------------------------------------*/
DIRSOUND::~DIRSOUND()
{
	WORD x;

	for ( x=0; x < ds_NUMCHANNELS; x++ )
	{
		if ( lpdsb[x] != NULL )
		{
			DestroyBuffer( x );

			if (sound[x] != NULL)
			{
				delete sound[x];
			}
		}
	}
	(void)lpdirsnd->Release();	/* Nothing to do, if it errors */
}

/*-------------------------------------------------------------------*/
/*  FillBuffer() : Fill Sound Buffer                                 */
/*-------------------------------------------------------------------*/
void DIRSOUND::FillBuffer( WORD channel )
{
	LPVOID write1;
	DWORD length1;
	LPVOID write2;
	DWORD length2;
	HRESULT hr;

  hr = lpdsb[channel]->Lock( iCnt * len[channel], len[channel],
    &write1, &length1, &write2, &length2, 0 );

	if (hr == DSERR_BUFFERLOST)
	{
		lpdsb[channel]->Restore();

		hr = lpdsb[channel]->Lock( iCnt * len[channel], len[channel],
      &write1, &length1, &write2, &length2, 0 );
	}

	if (hr != DS_OK)
	{
    InfoNES_MessageBox( "Lock() Failed." );
		exit(-1);
	}

	CopyMemory( write1, sound[channel], length1 );

	if (write2 != NULL)
	{
		CopyMemory(write2, sound[channel] + length1, length2);
	}

	hr = lpdsb[channel]->Unlock(write1, length1, write2, length2);

	if (hr != DS_OK)
	{
    InfoNES_MessageBox( "Unlock() Failed." );
		exit(-1);
	}
}

/*-------------------------------------------------------------------*/
/*  CreateBuffer() : Create IDirectSoundBuffer                       */
/*-------------------------------------------------------------------*/
void DIRSOUND::CreateBuffer(WORD channel)
{
	DSBUFFERDESC dsbdesc;
	PCMWAVEFORMAT pcmwf;
	HRESULT hr;

	memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT));
	pcmwf.wf.wFormatTag 		 = WAVE_FORMAT_PCM;
	pcmwf.wf.nChannels			 = ds_CHANSPERSAMPLE;
	pcmwf.wf.nSamplesPerSec  = ds_SAMPLERATE;
	pcmwf.wf.nBlockAlign		 = ds_CHANSPERSAMPLE * ds_BITSPERSAMPLE / 8;
	pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
	pcmwf.wBitsPerSample		 = ds_BITSPERSAMPLE;

	memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
	dsbdesc.dwSize				= sizeof(DSBUFFERDESC);
	dsbdesc.dwFlags 			= 0;
	dsbdesc.dwBufferBytes = len[channel]*Loops;
	dsbdesc.lpwfxFormat 	= (LPWAVEFORMATEX)&pcmwf;

	hr = lpdirsnd->CreateSoundBuffer(&dsbdesc, &lpdsb[channel], NULL);

	if (hr != DS_OK)
	{
    InfoNES_MessageBox( "CreateSoundBuffer() Failed." );
		exit(-1);
	}
}

/*-------------------------------------------------------------------*/
/*  DestoryBuffer() : Destory IDirectSoundBuffer                     */
/*-------------------------------------------------------------------*/
void DIRSOUND::DestroyBuffer(WORD channel)
{
	DWORD hr;

	hr = lpdsb[channel]->Release();

	if (hr != DS_OK)
	{
    InfoNES_MessageBox( "Release() Failed." );
		exit(-1);
	}

	lpdsb[channel] = NULL;
}

/*-------------------------------------------------------------------*/
/*  AllocChannel() : Allocate channel for IDirectSoundBuffer         */
/*-------------------------------------------------------------------*/
WORD DIRSOUND::AllocChannel(void)
{
	WORD x;

	for (x=0;x<ds_NUMCHANNELS;x++)
	{
		if (lpdsb[x] == NULL)
		{
			break;
		}
	}

	if ( x == ds_NUMCHANNELS )
	{
    /* No available channel */
    InfoNES_MessageBox( "AllocChannel() Failed." );
		exit(-1);
	}

	return (x);
}

/*-------------------------------------------------------------------*/
/*  Play() : Play Sound                                              */
/*-------------------------------------------------------------------*/
void DIRSOUND::Start(WORD channel, BOOL looping)
{
	HRESULT hr;

	hr = lpdsb[channel]->Play( 0, 0, looping == TRUE ? DSBPLAY_LOOPING : 0 );

	if ( hr != DS_OK )
	{
    InfoNES_MessageBox( "Play() Failed." );
		exit(-1);
	}
}

/*-------------------------------------------------------------------*/
/*  Stop() : Stop Sound                                              */
/*-------------------------------------------------------------------*/
void DIRSOUND::Stop(WORD channel)
{
	lpdsb[channel]->Stop();
}

/*-------------------------------------------------------------------*/
/*  UnLoadWave() : Destory Channel for IDirectSoundBuffer            */
/*-------------------------------------------------------------------*/
void DIRSOUND::UnLoadWave(WORD channel)
{
	DestroyBuffer(channel);

	if ( sound[channel] != NULL )
	{
		delete sound[channel];
	}
}

/*-------------------------------------------------------------------*/
/*  SoundOpen() : Open Devices for Sound Emulation                   */
/*-------------------------------------------------------------------*/
BOOL DIRSOUND::SoundOpen(int samples_per_sync, int sample_rate)
{
  ch1 = AllocChannel();

	sound[ch1] = new BYTE[ samples_per_sync ];
	len[ch1]	 = samples_per_sync;

	if ( sound[ch1] == NULL )
	{
    InfoNES_MessageBox( "new BYTE[] Failed." );
		exit(-1);
	}
  CreateBuffer( ch1 );

  /* Clear buffer */
  FillMemory( sound[ch1], len[ch1], 0 );
  for ( int i = 0; i < Loops; i++ )
    SoundOutput( len[ch1], sound[ch1] );

  /* Begin to play sound */
  Start( ch1, TRUE );

  return TRUE;
}

/*-------------------------------------------------------------------*/
/*  SoundClose() : Close Devices for Sound Emulation                 */
/*-------------------------------------------------------------------*/
void DIRSOUND::SoundClose( void )
{
  /* Stop to play sound */
  Stop( ch1 );

  UnLoadWave(ch1);
}

/*-------------------------------------------------------------------*/
/*  SoundOutput() : Output Sound to Device for Sound Emulation       */
/*-------------------------------------------------------------------*/
BOOL DIRSOUND::SoundOutput(int samples, BYTE *wave)
{
	/* Buffering sound data */
	CopyMemory( sound[ ch1 ], wave, samples );

  /* Copying to sound data buffer */
  FillBuffer( ch1 );

  /* Play if Counter reaches buffer edge */
  if ( Loops == ++iCnt )
  {
    iCnt = 0;
  }
  return TRUE;
}

/*-------------------------------------------------------------------*/
/*  SoundMute() : Sound Mute for Sound Emulation                     */
/*-------------------------------------------------------------------*/
BOOL DIRSOUND::SoundMute( BOOL flag )
{
  if ( flag )
  {
    /* Mute on : Stop to play sound */
    Stop( ch1 );
  }
  else
  {
    /* Clear buffer */
    FillMemory( sound[ch1], len[ch1], 0 );
    for ( int i = 0; i < Loops; i++ )
      SoundOutput( len[ch1], sound[ch1] );

    /* Mute off : Begin to play sound */
    iCnt = Loops * 3 / 4;
    Start( ch1, TRUE );
  }
  return TRUE;
}

// End of InfoNES_Sound_Win.cpp

⌨️ 快捷键说明

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