内核技术中文网»首页 论坛 圈点 查看内容

0 评论

0 收藏

分享

请实现DirectSound播放器,线程播放

以下是一个使用DirectSound播放音频文件的示例代码:

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

// 定义音频缓冲区大小
#define BUFFER_SIZE 4096

// 音频文件路径
const char* audioFile = "path/to/audio.wav";

// 全局变量
LPDIRECTSOUND8 lpDirectSound = NULL;
LPDIRECTSOUNDBUFFER lpPrimaryBuffer = NULL;
LPDIRECTSOUNDBUFFER8 lpSecondaryBuffer = NULL;

// 音频播放线程函数
DWORD WINAPI AudioThread(LPVOID lpParam) {
    // 打开音频文件
    FILE* file;
    if (fopen_s(&file, audioFile, "rb") != 0) {
        std::cout << "无法打开音频文件" << std::endl;
        return 0;
    }

    // 创建音频缓冲区
    DSBUFFERDESC bufferDesc = {};
    bufferDesc.dwSize = sizeof(DSBUFFERDESC);
    bufferDesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY;
    bufferDesc.dwBufferBytes = BUFFER_SIZE;
    bufferDesc.guid3DAlgorithm = GUID_NULL;

    WAVEFORMATEX waveFormatEx = {};
    waveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
    waveFormatEx.nChannels = 2;              // 双声道
    waveFormatEx.nSamplesPerSec = 44100;      // 采样率为44.1kHz
    waveFormatEx.wBitsPerSample = 16;         // 每个样本16位
    waveFormatEx.nBlockAlign = (waveFormatEx.nChannels * waveFormatEx.wBitsPerSample) / 8;
    waveFormatEx.nAvgBytesPerSec = waveFormatEx.nSamplesPerSec * waveFormatEx.nBlockAlign;

    bufferDesc.lpwfxFormat = &waveFormatEx;

    if (FAILED(lpDirectSound->CreateSoundBuffer(&bufferDesc, &lpSecondaryBuffer, NULL))) {
        std::cout << "音频缓冲区创建失败" << std::endl;
        fclose(file);
        return 0;
    }

    // 读取音频数据
    char buffer[BUFFER_SIZE];
    DWORD bytesRead;
    DWORD writePos = 0;
    BOOL isPlaying = FALSE;

    while (fread(buffer, sizeof(char), BUFFER_SIZE, file) == BUFFER_SIZE) {
        lpSecondaryBuffer->Lock(writePos, BUFFER_SIZE, (LPVOID*)&buffer, &bytesRead, NULL, NULL, 0);

        // 将音频数据拷贝到缓冲区
        memcpy(buffer, buffer, bytesRead);

        lpSecondaryBuffer->Unlock((LPVOID)buffer, bytesRead, NULL, 0);

        writePos += bytesRead;

        // 开始播放音频
        if (!isPlaying) {
            isPlaying = TRUE;
            lpSecondaryBuffer->Play(0, 0 , DSBPLAY_LOOPING);
        }
    }

    fclose(file);

    // 等待音频播放完成
    DWORD status;

    do {
        lpSecondaryBuffer->GetStatus(&status);
        Sleep(100); 
    } while (status & DSBSTATUS_PLAYING);

    // 停止播放并释放资源
    if (lpSecondaryBuffer)
    {
        lpSecondaryBuffer->Stop();
        lpSecondaryBuffer->Release();
        lpSecondaryBuffer = NULL;
    }

    if (lpPrimaryBuffer)
    {
        lpPrimaryBuffer->Release();
        lpPrimaryBuffer = NULL;
    }

    if (lpDirectSound)
    {
        lpDirectSound->Release();
        lpDirectSound = NULL;
    }

    return 0;
}

int main() {
    // 初始化DirectSound
    if (FAILED(DirectSoundCreate8(NULL, &lpDirectSound, NULL))) {
        std::cout << "DirectSound初始化失败" << std::endl;
        return 1;
    }

    if (FAILED(lpDirectSound->SetCooperativeLevel(GetDesktopWindow(), DSSCL_PRIORITY))) {
        std::cout << "设置协作级别失败" << std::endl;
        return 1;
    }

    // 创建主音频缓冲区
    DSBUFFERDESC bufferDesc = {};
    bufferDesc.dwSize = sizeof(DSBUFFERDESC);
    bufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;

    if (FAILED(lpDirectSound->CreateSoundBuffer(&bufferDesc, &lpPrimaryBuffer, NULL)))
    {
        std::cout << "主音频缓冲区创建失败" << std::endl;
        return 1;
    }

    WAVEFORMATEX waveFormatEx = {};
    waveFormatEx.wFormatTag = WAVE_FORMAT_PCM; 
    waveFormatEx.nChannels = 2;              // 双声道
    waveFormatEx.nSamplesPerSec = 44100;      // 采样率为44.1kHz
    waveFormatEx.wBitsPerSample = 16;         // 每个样本16位
    waveFormatEx.nBlockAlign = (waveFormatEx.nChannels * waveFormatEx.wBitsPerSample) / 8;
    waveFormatEx.nAvgBytesPerSec = waveFormatEx.nSamplesPerSec * waveFormatEx.nBlockAlign;

    if (FAILED(lpPrimaryBuffer->SetFormat(&waveFormatEx)))
    {
        std::cout << "设置主音频缓冲区格式失败" << std::endl;
        return 1;
    }

    // 创建音频播放线程
    HANDLE hAudioThread = CreateThread(NULL, 0, AudioThread, NULL, 0, NULL);

    // 等待线程结束
    WaitForSingleObject(hAudioThread, INFINITE);

    // 关闭DirectSound
    if (lpPrimaryBuffer)
    {
        lpPrimaryBuffer->Release();
        lpPrimaryBuffer = NULL;
    }

    if (lpDirectSound)
    {
        lpDirectSound->Release();
        lpDirectSound = NULL;
    }

    return 0;
}

请确保在项目中包含dsound.lib库文件,并将路径更改为要播放的音频文件的路径。这个示例代码通过创建一个独立的音频播放线程来实现后台播放。<br/><br/><br/><p style="color:#CCCCCC;font-size:12px;">内容由零声教学AI助手提供,问题来源于学员提问</p>

回复

举报 使用道具

全部回复
暂无回帖,快来参与回复吧
主题 6339
回复 0
粉丝 0
扫码获取每晚技术直播链接
快速回复 返回顶部 返回列表