使用Windows API实现本地音频设备的枚举和播放

使用Windows API实现本地扬声器的枚举和测试可以使用Multimedia Device API中的waveOut接口。下面是一个简单的C++示例代码,用于枚举本地扬声器设备,并播放一段测试音频。

#include <iostream>
#include <Windows.h>
#include <mmsystem.h>

#pragma comment(lib, "winmm.lib")

void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
    // 这里可以处理音频播放结束的事件
}

int main()
{
    // 枚举音频设备
    std::cout << "Enumerating audio devices..." << std::endl;

    WAVEOUTCAPS waveOutCaps;
    for (UINT i = 0; i < waveOutGetNumDevs(); ++i)
    {
        waveOutGetDevCaps(i, &waveOutCaps, sizeof(WAVEOUTCAPS));
        std::cout << "Device #" << i << ": " << waveOutCaps.szPname << std::endl;
    }

    // 打开默认音频设备
    std::cout << "Opening default audio device..." << std::endl;

    HWAVEOUT hWaveOut;
    WAVEFORMATEX waveFormat;
    MMRESULT result;

    // 设置音频格式
    waveFormat.wFormatTag = WAVE_FORMAT_PCM;
    waveFormat.nChannels = 2;
    waveFormat.nSamplesPerSec = 44100;
    waveFormat.nAvgBytesPerSec = 176400;
    waveFormat.nBlockAlign = 4;
    waveFormat.wBitsPerSample = 16;
    waveFormat.cbSize = 0;

    // 打开音频设备
    result = waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveFormat, (DWORD_PTR)waveOutProc, 0, CALLBACK_FUNCTION);
    if (result != MMSYSERR_NOERROR)
    {
        std::cout << "Failed to open audio device" << std::endl;
        return 1;
    }

    // 播放音频数据
    std::cout << "Playing audio..." << std::endl;

    BYTE audioData[44100 * 4]; // 1秒钟的音频数据
    for (int i = 0; i < 44100; ++i)
    {
        audioData[i * 4] = 0x80;
        audioData[i * 4 + 1] = 0x80;
        audioData[i * 4 + 2] = 0x8F;
        audioData[i * 4 + 3] = 0xFF;
    }

    WAVEHDR waveHeader;
    waveHeader.lpData = (LPSTR)audioData;
    waveHeader.dwBufferLength = sizeof(audioData);
    waveHeader.dwFlags = 0;

    result = waveOutPrepareHeader(hWaveOut, &waveHeader, sizeof(WAVEHDR));
    if (result != MMSYSERR_NOERROR)
    {
        std::cout << "Failed to prepare audio header" << std::endl;
        return 1;
    }

    result = waveOutWrite(hWaveOut, &waveHeader, sizeof(WAVEHDR));
    if (result != MMSYSERR_NOERROR)
    {
        std::cout << "Failed to write audio data" << std::endl;
        return 1;
    }

    // 等待播放完成
    while ((waveHeader.dwFlags & WHDR_DONE) == 0) {
        Sleep(100);
    }
        
    // 关闭音频设备
    std::cout << "Closing audio device..." << std::endl;
    waveOutUnprepareHeader(hWaveOut, &waveHeader, sizeof(WAVEHDR));
    waveOutClose(hWaveOut);

    return 0;
}

代码中,首先通过调用 `waveOutGetNumDevs()` 函数枚举本地扬声器设备,并打印设备列表。然后使用 `waveOutOpen()` 函数打开默认音频设备,并设置音频格式。接着生成一段测试音频数据,使用 `waveOutPrepareHeader()` 函数准备音频数据,使用 `waveOutWrite()` 函数将音频数据写入设备播放。最后在循环中等待音频播放完成,调用 `waveOutClose()` 函数关闭音频设备。 如果需要处理音频播放结束的事件,可以在 `waveOutProc()` 回调函数中进行处理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是使用 Windows SDK 版本为 8.1 实现枚举 WPD 设备内容的基本步骤: 1. 初始化 WPD API,并获取 WPD 服务的 IUnknown 接口。 ``` CoInitialize(NULL); HRESULT hr = CoCreateInstance( __uuidof(PortableDeviceManager), NULL, CLSCTX_INPROC_SERVER, __uuidof(IPortableDeviceManager), (VOID**)&pPortableDeviceManager ); ``` 2. 使用 IPortableDeviceManager::GetDevices 方法获取连接到计算机上的 WPD 设备。 ``` GUID guid = { 0 }; DWORD dwCount = 0; hr = pPortableDeviceManager->GetDevices(&guid, NULL, &dwCount); if (SUCCEEDED(hr) && dwCount > 0) { PWSTR* pDeviceIDs = new PWSTR[dwCount]; hr = pPortableDeviceManager->GetDevices(&guid, pDeviceIDs, &dwCount); if (SUCCEEDED(hr)) { // 枚举设备内容 for (DWORD i = 0; i < dwCount; i++) { EnumerateDeviceContent(pDeviceIDs[i]); } } // 释放设备 ID 数组 for (DWORD i = 0; i < dwCount; i++) { CoTaskMemFree(pDeviceIDs[i]); } delete[] pDeviceIDs; } ``` 3. 枚举设备内容,使用 IPortableDeviceContent 接口获取设备内容信息。 ``` void EnumerateDeviceContent(PCWSTR pszDeviceID) { IPortableDevice* pPortableDevice = NULL; IPortableDeviceContent* pPortableDeviceContent = NULL; // 连接到设备 HRESULT hr = CoCreateInstance( __uuidof(PortableDevice), NULL, CLSCTX_INPROC_SERVER, __uuidof(IPortableDevice), (VOID**)&pPortableDevice ); if (SUCCEEDED(hr)) { hr = pPortableDevice->Open(pszDeviceID, pPortableDeviceCallback); if (SUCCEEDED(hr)) { hr = pPortableDevice->Content(&pPortableDeviceContent); if (SUCCEEDED(hr)) { // 枚举设备内容 EnumerateContent(pPortableDeviceContent, L""); } } // 关闭设备连接 pPortableDevice->Close(); } // 释放设备对象 if (pPortableDevice) { pPortableDevice->Release(); } if (pPortableDeviceContent) { pPortableDeviceContent->Release(); } } ``` 4. 使用 IPortableDeviceContent::EnumObjects 方法枚举设备内容。 ``` void EnumerateContent(IPortableDeviceContent* pContent, PCWSTR pszObjectID) { IEnumPortableDeviceObjectIDs* pEnum = NULL; // 枚举对象 ID HRESULT hr = pContent->EnumObjects(0, pszObjectID, NULL, &pEnum); if (SUCCEEDED(hr)) { DWORD dwFetched = 0; PWSTR pszObjectIDs[MAX_OBJECTS] = { 0 }; // 获取对象 ID 数组 hr = pEnum->Next(MAX_OBJECTS, pszObjectIDs, &dwFetched); if (SUCCEEDED(hr)) { // 枚举每个对象 for (DWORD i = 0; i < dwFetched; i++) { EnumerateObject(pContent, pszObjectIDs[i]); } } // 释放对象 ID 数组 for (DWORD i = 0; i < dwFetched; i++) { CoTaskMemFree(pszObjectIDs[i]); } } // 释放枚举器对象 if (pEnum) { pEnum->Release(); } } ``` 5. 使用 IPortableDeviceContent::Properties 方法获取对象属性。 ``` void EnumerateObject(IPortableDeviceContent* pContent, PCWSTR pszObjectID) { IPortableDeviceProperties* pProperties = NULL; // 获取对象属性 HRESULT hr = pContent->Properties(&pProperties); if (SUCCEEDED(hr)) { IPortableDeviceValues* pValues = NULL; // 获取对象属性值 hr = pProperties->GetValues(pszObjectID, NULL, &pValues); if (SUCCEEDED(hr)) { // 输出对象属性值 OutputObjectProperties(pValues); } // 释放属性值对象 if (pValues) { pValues->Release(); } } // 释放属性对象 if (pProperties) { pProperties->Release(); } } ``` 以上就是使用 Windows SDK 版本为 8.1 实现枚举 WPD 设备内容的基本步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值