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

📄 audio.c

📁 DC的SEGA_GG模拟器源代码
💻 C
字号:
#include "windows.h"
#include "dsound.h"
#include "dinput.h"
#include "shared.h"
#include "audio.h"
#include "input.h"
#include "main.h"
#include "registry.h"

static LPDIRECTSOUND							pDirectSound		= NULL;
static LPDIRECTSOUNDBUFFER						pPrimaryBuffer		= NULL;
static LPDIRECTSOUNDBUFFER						pSoundBuffer		= NULL;
static void										*pSimpleSoundBuffer	= NULL;
static HWAVEOUT									hWaveOut;
static WAVEHDR									WaveHeader;
static HANDLE									RecordFileHandle	= INVALID_HANDLE_VALUE;
static BOOL										RecordInProgress	= FALSE;
static unsigned int								RecordedBytes		= 0;
static WAV_HEADER								WavFileHeader		= { {"RIFF", 0},
																		{"WAVE"},
																		{"fmt ", sizeof(WAVEFORMATEX)},
																		{WAVE_FORMAT_PCM, 2, 0, 0, 4, 16, 0},
																		{"data", 0} };

BOOL InitAudio(HWND hwnd, int Frequency, int UpdateFrequency)
{
    DSBUFFERDESC    SoundBufferDesc;
	WAVEFORMATEX	WaveFormat;

	RecordInProgress = FALSE;

	SetWavHeaderInfo(0, Frequency, UpdateFrequency);

	// Create the direct sound interface
    if (DirectSoundCreate(NULL, &pDirectSound, NULL) != DS_OK)
	{
		TidyAudio();

		// Try simple audio for windows NT
		return InitSimpleAudio(hwnd, Frequency, UpdateFrequency);
	}

	// Set the cooperative level
    if (IDirectSound_SetCooperativeLevel(pDirectSound, hwnd, DSSCL_EXCLUSIVE) != DS_OK)
    {
		TidyAudio();

		// Try simple audio for windows NT
		return InitSimpleAudio(hwnd, Frequency, UpdateFrequency);
    }

	// Set the speaker configuration
	IDirectSound_SetSpeakerConfig(pDirectSound, DSSPEAKER_STEREO);

	// Initialise the sound buffer description
    memset(&SoundBufferDesc, 0, sizeof(DSBUFFERDESC));
	// Set the size of the structure
    SoundBufferDesc.dwSize = sizeof(DSBUFFERDESC);
	// We require a primary buffer
    SoundBufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER;

	// Create the sound buffer
    if (IDirectSound_CreateSoundBuffer(pDirectSound, &SoundBufferDesc, &pPrimaryBuffer, NULL) != DS_OK)
    {
		TidyAudio();

		// Try simple audio for windows NT
		return InitSimpleAudio(hwnd, Frequency, UpdateFrequency);
    }

	WaveFormat.wFormatTag		= WAVE_FORMAT_PCM;
	WaveFormat.nChannels		= 2;
	WaveFormat.nSamplesPerSec	= Frequency;
	WaveFormat.nAvgBytesPerSec	= Frequency * 4;
	WaveFormat.nBlockAlign		= 4;
	WaveFormat.wBitsPerSample	= 16;
	WaveFormat.cbSize			= 0;
	SoundBufferDesc.dwFlags		  = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLVOLUME;
    SoundBufferDesc.dwBufferBytes = (Frequency / UpdateFrequency) * 4 * NO_OF_AUDIO_BUFFERS;
    SoundBufferDesc.lpwfxFormat   = &WaveFormat;

	if (IDirectSoundBuffer_SetFormat(pPrimaryBuffer, &WaveFormat) != DS_OK)
	{
		TidyAudio();
		return FALSE;
	}

    if (IDirectSound_CreateSoundBuffer(pDirectSound, &SoundBufferDesc, &pSoundBuffer, NULL) != DS_OK)
    {
		TidyAudio();
		return FALSE;
    }

	return TRUE;
}

BOOL InitSimpleAudio(HWND hwnd, int Frequency, int UpdateFrequency)
{
	unsigned int	WavSize = sizeof(WAV_HEADER) + ((Frequency / UpdateFrequency) * 4 * NO_OF_AUDIO_BUFFERS);

	// Allocate the wave buffer
	pSimpleSoundBuffer = malloc(WavSize);

	if (!pSimpleSoundBuffer) return FALSE;

	SetWavHeaderInfo(WavSize, Frequency, UpdateFrequency);

	memset(pSimpleSoundBuffer, 0, WavSize);
	memcpy(pSimpleSoundBuffer, &WavFileHeader, sizeof(WAV_HEADER));

	waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER, (LPWAVEFORMATEX)&WavFileHeader.WaveFormat, (LONG)hwnd, 0, CALLBACK_WINDOW);

	memset(&WaveHeader, 0, sizeof(WAVEHDR));

	WaveHeader.lpData		  = (char *)((int)pSimpleSoundBuffer + sizeof(WAV_HEADER));
	WaveHeader.dwBufferLength = (Frequency / UpdateFrequency) * 4 * NO_OF_AUDIO_BUFFERS;
	WaveHeader.dwLoops		  = 0x7FFFFFFF;
	WaveHeader.dwFlags		  = WHDR_BEGINLOOP | WHDR_ENDLOOP;

	return TRUE;
}

void SetWavHeaderInfo(unsigned int WavSize, int Frequency, int UpdateFrequency)
{
	WavFileHeader.RiffHeader.Length				= WavSize - sizeof(RIFF_HEADER);
	WavFileHeader.WaveFormat.nSamplesPerSec		= Frequency;
	WavFileHeader.WaveFormat.nAvgBytesPerSec	= Frequency * 4;
	WavFileHeader.DataChunk.Length				= (Frequency / UpdateFrequency) * 4 * NO_OF_AUDIO_BUFFERS;
}

void StopAudio(void)
{
	if (pSimpleSoundBuffer)	waveOutReset(hWaveOut);
	if (pSoundBuffer)		IDirectSoundBuffer_Stop(pSoundBuffer);
}

void UpdateAudio(short *pBuffer, int BufferSize, int Frame)
{
    LPVOID  pAudio1;
    int     AudioBytes1;
    LPVOID  pAudio2;
    int     AudioBytes2;
	DWORD	WritePos;

	BufferSize *= 4;
	WritePos    = ((Frame + (NO_OF_AUDIO_BUFFERS >> 1)) % NO_OF_AUDIO_BUFFERS) * BufferSize;

	if (pSimpleSoundBuffer)
	{
		memcpy((char *)((int)pSimpleSoundBuffer + sizeof(WAV_HEADER) + WritePos), pBuffer, BufferSize);

		if (Frame == 0) 
		{
			waveOutReset(hWaveOut);
			while (waveOutUnprepareHeader(hWaveOut, &WaveHeader, sizeof(WAVEHDR)) == WAVERR_STILLPLAYING); 
			waveOutPrepareHeader(hWaveOut, &WaveHeader, sizeof(WAVEHDR)); 
			waveOutWrite(hWaveOut, &WaveHeader, sizeof(WAVEHDR)); 
		}
	}
	else if (pSoundBuffer)
	{
		// Lock the sound buffer
		if (IDirectSoundBuffer_Lock(pSoundBuffer, WritePos, BufferSize, &pAudio1, &AudioBytes1, &pAudio2, &AudioBytes2, 0) == DS_OK)
		{
			// Buffer is now locked, write first block
			memcpy(pAudio1, (char *)pBuffer, AudioBytes1);

			// See if we need to write a second block
			if (AudioBytes2)
			{
				// Yes, so write second block
				memcpy(pAudio2, (char *)((int)pBuffer + AudioBytes1), AudioBytes2);
			}

			// Unlock buffer
			IDirectSoundBuffer_Unlock(pSoundBuffer, pAudio1, AudioBytes1, pAudio2, AudioBytes2);
		}

		if (Frame == 0)
		{
			IDirectSoundBuffer_SetCurrentPosition(pSoundBuffer, 0);
			IDirectSoundBuffer_Play(pSoundBuffer, 0, 0, DSBPLAY_LOOPING);
		}
	}
}

void TidyAudio(void)
{
	if (RecordInProgress) CloseSoundRecording();

	if (pSimpleSoundBuffer)
	{
		waveOutReset(hWaveOut);
		while (waveOutUnprepareHeader(hWaveOut, &WaveHeader, sizeof(WAVEHDR)) == WAVERR_STILLPLAYING); 
		waveOutClose(hWaveOut);
		free(pSimpleSoundBuffer);
		pSimpleSoundBuffer = NULL;
	}
	
	if (pSoundBuffer) 
	{
		IDirectSoundBuffer_Stop(pSoundBuffer);
		IDirectSoundBuffer_Release(pSoundBuffer);
		pSoundBuffer = NULL;
	}

	if (pPrimaryBuffer) 
	{
		IDirectSoundBuffer_Stop(pPrimaryBuffer);
		IDirectSoundBuffer_Release(pPrimaryBuffer);
		pPrimaryBuffer = NULL;
	}

	if (pDirectSound)
	{
		IDirectSound_Release(pDirectSound);
		pDirectSound = NULL;
	}
}

BOOL CreateSoundRecording(void)
{
	char			Filename[MAX_PATH];

	RecordInProgress = TRUE;

	wsprintf(Filename, "%s%s.gym", RegistryInfo.SoundRecordPath, GetGameName());

	RecordFileHandle = CreateFile(Filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);

	if (RecordFileHandle == INVALID_HANDLE_VALUE) return FALSE;

	snd.log = TRUE;

	return TRUE;
}

void UpdateSoundRecording(int Data)
{
	unsigned int	BytesWritten;

	if (RecordFileHandle != INVALID_HANDLE_VALUE)
	{
	    WriteFile(RecordFileHandle, &Data, 1, &BytesWritten, NULL);
	}
}

void CloseSoundRecording(void)
{
	snd.log = FALSE;

	CloseHandle(RecordFileHandle);

	RecordFileHandle = INVALID_HANDLE_VALUE;
	RecordInProgress = FALSE;

	MessageBox(NULL, "Sound recording complete.", "", MB_OK);
}

⌨️ 快捷键说明

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