首页 > 其他分享 >DSound播放WAV文件

DSound播放WAV文件

时间:2024-10-13 22:34:02浏览次数:9  
标签:dataChunkId format buffer wave file DSound WAV 播放 ds

/***************************************************************************************
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

相关文章

  • windows连接两个音响同时播放
    应用软件:voicemeter下载地址:https://pan.baidu.com/s/1-w54Sdf807WBhXW1VfTTPA?pwd=vx5eA1、A2选择对应音响或耳机声音输出选择:voicemeterinput延迟调整:voicemeter——>menu——>systemsettings/options调整小爱音箱的延迟为712这样的话,两个音箱就是同时发声,会很舒服......
  • 前端知识整理(全屏播放器 CSS JavaScript 轮转播放 jquery库 AJAX 画布 网页测试)
    currenttime在前端开发中,“currenttime”通常指的是获取用户设备的当前时间。这可以通过JavaScript来实现,下面是一个简单的示例代码,展示如何获取并显示当前时间:<!DOCTYPEhtml><html><head><title>显示当前时间</title></head><body><h1>当前时间:</h1><pid="d......
  • FFmpeg开发笔记(五十六)使用Media3的Exoplayer播放网络视频
    ​Android早期的MediaPlayer控件对于网络视频的兼容性很差,所以后来单独推出了Exoplayer库增强支持网络视频,在《AndroidStudio开发实战:从零基础到App上线(第3版)》一书第14章的“14.3.3 新型播放器ExoPlayer”就详细介绍了Exoplayer库的详细用法。现在Android官方再次升级Exop......
  • 基于微信小程序的音乐在线播放系统的设计与实现springboot+vue的项目
    课题说明基于SpringBoot+Vue的微信小程序音乐在线播放系统为用户带来便捷的音乐体验。SpringBoot作为后端框架,负责音乐资源的存储管理、用户数据处理及接口服务。它确保音乐文件的安全存储和稳定传输,同时管理用户的播放历史、收藏列表等数据。Vue构建的微信小程序......
  • Air201资产定位模组LuatOS:录音&播放录音功能的操作方法
    ​ 一直有小伙伴们问,迷你小巧的合宙Air201虽然有很多优点,超低功耗、精准定位,那么它是否支持录音、播放录音功能? 那必须能!高集成化设计的Air201自带了ES8311音频解码芯片(AudioCodec)及MIC麦克,可支持本地的录音功能;使用配套喇叭即可将录音保存的数据进行播放,操作极为方便。本......
  • android试题编号:2-2-8车载媒体播放 App
    (1)任务描述中控大屏仪表屏幕中间显示媒体组件,组件内上方显示正在播放的媒体信息例如“歌曲名称”“音视频名称”信息栏、“音量显示”。信息栏下方显示播放控制按钮,“播放/暂停”“上一曲下一曲”“音量滑块”“静音”,在操控设备中点击“播放/暂停”,仪表屏中的按钮随之切换“......
  • 棉花音乐 1.41.2 | 支持百度/阿里云盘的多功能音乐播放器
    棉花音乐是一款简洁的本地及网盘音乐播放器,支持本地歌曲、百度网盘、阿里云盘、WebDAV、GoogleDrive、OneDrive、Dropbox等网盘歌曲播放,支持Plex、Emby、Jellyfin、Subsonic媒体服务器。同时支持Android、Windows、Mac、Linux平台。主要功能包括播放历史记录、支持创建歌......
  • 使用ffmpeg修复本地视频文件(mp4)播放时进度条无法拖动的问题
    右击视频文件查看属性,在详细信息页查看视频时长,显示为空,推测进度条无法拖动的原因是时间轴损坏于是采用了以下解决办法将视频分离出来,命名为video.mp4ffmpeg-i视频名称.mp4-map0:v-vcodeccopy-bsf:vh264_mp4toannexbvideo.mp4将音频分离出来,命名为audio.wavffm......
  • 如何基于 XSwitch 拨通sip号码并播放声音
    关键点部署Xswitchdocker模式部署开启Xcc高级-->模块配置-->Xcc-->启用Xcc模块,开启nats-url  nats://127.0.0.1:4222启用,其他配置不用修改使用默认的即可部署NATSdocker模式部署(docker模式没有账号密码)配置环境变量  有三个  NATS_URL:nats://你部署nats服务......
  • 《DNK210使用指南 -CanMV版 V1.0》第二十八章 音频播放实验
    第二十八章音频播放实验1)实验平台:正点原子DNK210开发板2)章节摘自【正点原子】DNK210使用指南-CanMV版V1.03)购买链接:https://detail.tmall.com/item.htm?&id=7828013987504)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/k210/ATK-DNK210.html5)正点原......