DSound播放WAV文件

/***************************************************************************************
PURPOSE:
    Lock Load Playing Demo
 ***************************************************************************************/

#define DIRECTINPUT_VERSION 0x0800

#include <windows.h>
#include <stdio.h>
#include <dsound.h>
#include <iostream>
#include <fstream>

#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "dsound.lib")

#pragma warning(disable : 4996)

#define Safe_Release(p) if((p)) (p)->Release();

// window handles, class and caption text.
HWND g_hwnd;
char g_class_name[] = "LockLoadClass";

int width = 400;
int height = 400;

IDirectSound8* g_ds;           // directsound component
IDirectSoundBuffer8* g_ds_buffer;    // sound buffer object
LPDIRECTSOUNDBUFFER ds;
HANDLE hEvent = NULL;
BYTE* ptr2 = nullptr;
BYTE* ptr = nullptr;

DWORD size2 = 0;
DWORD size = 0;

bool LoadWAV(const char* filename, WAVEFORMATEX* wfx, BYTE** buffer, DWORD* bufferSize) {
	std::ifstream file(filename, std::ios::binary);
	if (!file.is_open()) {
		std::cerr << "Failed to open file: " << filename << std::endl;
		return false;
	}

	// 读取RIFF头
	char riffHeader[4];
	file.read(riffHeader, 4);
	if (riffHeader[0] != 'R' || riffHeader[1] != 'I' || riffHeader[2] != 'F' || riffHeader[3] != 'F') {
		std::cerr << "Not a valid WAV file (missing RIFF header)" << std::endl;
		return false;
	}

	// 读取文件大小
	DWORD fileSize;
	file.read(reinterpret_cast<char*>(&fileSize), sizeof(fileSize));

	// 读取WAVE头
	char waveHeader[4];
	file.read(waveHeader, 4);
	if (waveHeader[0] != 'W' || waveHeader[1] != 'A' || waveHeader[2] != 'V' || waveHeader[3] != 'E') {
		std::cerr << "Not a valid WAV file (missing WAVE header)" << std::endl;
		return false;
	}

	// 读取fmt chunk
	char fmtChunkId[4];
	file.read(fmtChunkId, 4);
	if (fmtChunkId[0] != 'f' || fmtChunkId[1] != 'm' || fmtChunkId[2] != 't' || fmtChunkId[3] != ' ') {
		std::cerr << "Missing fmt chunk" << std::endl;
		return false;
	}

	DWORD fmtChunkSize;
	file.read(reinterpret_cast<char*>(&fmtChunkSize), sizeof(fmtChunkSize));
	//if (fmtChunkSize != sizeof(WAVEFORMATEX)) {
	//	std::cerr << "Invalid fmt chunk size" << std::endl;
	//	return false;
	//}
	int wfx_size = sizeof(WAVEFORMATEX);
	file.read(reinterpret_cast<char*>(wfx), wfx_size);

	int reverse_len = 20 - wfx_size;
	BYTE* reverse_data = new BYTE[reverse_len];
	file.read(reinterpret_cast<char*>(reverse_data), reverse_len);
	delete[] reverse_data;
	reverse_data = NULL;

	//// 读取data chunk
 //   char dataChunkId[4];
	//file.read(dataChunkId, 4);
	//if ((dataChunkId[0] != 'd' || dataChunkId[1] != 'a' || dataChunkId[2] != 't' || dataChunkId[3] != 'a') 
	//	|| (dataChunkId[0] != 'd' || dataChunkId[1] != 'a' || dataChunkId[2] != 't' || dataChunkId[3] != 'a')
	//	) {
	//	std::cerr << "Missing data chunk" << std::endl;
	//	return false;
	//}

	DWORD dataSize;
	file.read(reinterpret_cast<char*>(&dataSize), sizeof(dataSize));

	*buffer = new BYTE[dataSize];
	file.read(reinterpret_cast<char*>(*buffer), dataSize);

	*bufferSize = dataSize;

	file.close();
	return true;
}



LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
	switch (uMsg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	default:
		return DefWindowProc(hwnd, uMsg, wParam, lParam);
	}
}

bool bStop = false;

void PlayWAV()
{
	// readies all or part of the buffer for a data write and returns pointers to which data can be written
	static DWORD count = 0;
	if (SUCCEEDED(g_ds_buffer->Lock(0, 0, (void**)&ptr, &size2, NULL, 0, DSBLOCK_ENTIREBUFFER)))
	{
		if (count >= size) {
			bStop = true;
			return;
		}
		/*for (DWORD i = 0; i < size2; i++)
			ptr[i] = ptr2[i];*/
		int re_file_size = size - count  ;
		if (re_file_size > size2) {
			memcpy(ptr, ptr2, size2);
		}
		else {
			memcpy(ptr, ptr2, re_file_size);
		}
        
		ptr2+=size2;
		count+=size2;
		
	}

	// releases a locked sound buffer
	g_ds_buffer->Unlock(ptr, size2, NULL, 0);

	// play sound looping

	// sets the position of the play cursor, 
	// which is the point at which the next byte of data is read from the buffer.
	g_ds_buffer->SetCurrentPosition(0);

	// set the attenuation of the sound
	g_ds_buffer->SetVolume(DSBVOLUME_MAX);

	// causes the sound buffer to play, starting at the play cursor.
	//g_ds_buffer->Play(0, 0, DSBPLAY_LOOPING);
	g_ds_buffer->Play(0, 0, 0);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
{

	// 注册窗口类
	WNDCLASS wc = {};
	wc.lpfnWndProc = WindowProc;
	wc.hInstance = hInstance;
	wc.lpszClassName = "D3DWindowClass";
	RegisterClass(&wc);

	// 创建窗口
    g_hwnd = CreateWindowEx(
		0,
		"D3DWindowClass",
		"D3D Window",
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, width, height,
		NULL, NULL, hInstance, NULL
	);

	if (!g_hwnd) {
		std::cerr << "Failed to create window." << std::endl;
		return -1;
	}

	ShowWindow(g_hwnd, nCmdShow);

    // initialize and configure directsound

    // creates and initializes an object that supports the IDirectSound8 interface
    if (FAILED(DirectSoundCreate8(NULL, &g_ds, NULL)))
    {
        MessageBox(NULL, "Unable to create DirectSound object", "Error", MB_OK);
        return 0;
    }

    // set the cooperative level of the application for this sound device
    g_ds->SetCooperativeLevel(g_hwnd, DSSCL_NORMAL);

    // create a sound buffer

    // setup the WAVEFORMATEX structure
    WAVEFORMATEX wave_format;

    ZeroMemory(&wave_format, sizeof(WAVEFORMATEX));

    //wave_format.wFormatTag = WAVE_FORMAT_PCM;
    //wave_format.nChannels = 1;        // mono
    //wave_format.nSamplesPerSec = 11025;
    //wave_format.wBitsPerSample = 16;
    //wave_format.nBlockAlign = (wave_format.wBitsPerSample / 8) * wave_format.nChannels;
    //wave_format.nAvgBytesPerSec = wave_format.nSamplesPerSec * wave_format.nBlockAlign;

	
	
	bool bRet = LoadWAV("input5.wav", &wave_format, &ptr2, &size);
	if (!bRet) {
		int err = GetLastError();
		//std::cerr << "Failed to load WAV file." << std::endl;
		g_ds_buffer->Release();
		g_ds->Release();
		ds->Release();
	}

    // setup the DSBUFFERDESC structure
    DSBUFFERDESC ds_buffer_desc;

    // zero out strcutre
    ZeroMemory(&ds_buffer_desc, sizeof(DSBUFFERDESC));

    ds_buffer_desc.dwSize = sizeof(DSBUFFERDESC);
    ds_buffer_desc.dwFlags = DSBCAPS_CTRLVOLUME;
    ds_buffer_desc.dwBufferBytes = wave_format.nAvgBytesPerSec * 2;  // 2 seconds
    ds_buffer_desc.lpwfxFormat = &wave_format;
	ds_buffer_desc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_GLOBALFOCUS;

    // create the fist version object
    if (FAILED(g_ds->CreateSoundBuffer( &ds_buffer_desc, &ds, NULL)))
    {
        // error ocuurred
        MessageBox(NULL, "Unable to create sound buffer", "Error", MB_OK);
    }
    else
    {
        // get the version 8 interface
        ds->QueryInterface(IID_IDirectSoundBuffer8, (void**)&g_ds_buffer);

        // release the original interface
        ds->Release();

        // lock buffer, fill with random values, and unlock.

		PlayWAV();
        
    }

	DWORD dwCurrentPlayCursor = 0, dwCurrentWriteCursor = 0;
	DWORD dw_last = 0;
    // start message pump, waiting for signal to quit.
    MSG msg;
    ZeroMemory(&msg, sizeof(MSG));

    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
		}
		else {

			

			if (g_ds_buffer->GetCurrentPosition(&dwCurrentPlayCursor, &dwCurrentWriteCursor) == DS_OK) {
				if ( (dw_last != 0) && (0 == dwCurrentPlayCursor)) {
					PlayWAV();
					dw_last = dwCurrentPlayCursor;
					
				}
				dw_last = dwCurrentPlayCursor;
			}
			if (bStop)
			{
				Sleep(10);
			}
			
		}
    }

    // release directsound objects
    g_ds->Release();

    UnregisterClass(g_class_name, hInstance);

    return (int)msg.wParam;
}

posted on 2024-10-13 22:31  thinkinc999  阅读(4)  评论(0编辑  收藏  举报

导航