/***************************************************************************************
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;
}
标签:dataChunkId,format,buffer,wave,file,DSound,WAV,播放,ds
From: https://www.cnblogs.com/thinkinc999/p/18463142