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

0 评论

0 收藏

分享

请实现DirectSound播放器,初始化和播放线程分离, 提供完整实现

以下是一个简单的实现DirectSound播放器的示例代码:

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

// 音频缓冲区大小(以字节为单位)
const int BUFFER_SIZE = 44100 * 2; // 1秒钟的音频

// DirectSound播放器类
class DirectSoundPlayer {
private:
    IDirectSound8* directSound;
    IDirectSoundBuffer* primaryBuffer;
    IDirectSoundBuffer8* secondaryBuffer;

public:
    DirectSoundPlayer() : directSound(nullptr), primaryBuffer(nullptr), secondaryBuffer(nullptr) {}

    bool Initialize(HWND hWnd) {
        // 创建DirectSound对象
        if (FAILED(DirectSoundCreate8(NULL, &directSound, NULL))) {
            std::cout << "Failed to create DirectSound object" << std::endl;
            return false;
        }

        // 设置协作级别
        if (FAILED(directSound->SetCooperativeLevel(hWnd, DSSCL_PRIORITY))) {
            std::cout << "Failed to set cooperative level" << std::endl;
            return false;
        }

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

        if (FAILED(directSound->CreateSoundBuffer(&bufferDesc, &primaryBuffer, nullptr))) {
            std::cout << "Failed to create primary buffer" << std::endl;
            return false;
        }

        // 设置主缓冲区格式为PCM音频流
        WAVEFORMATEX waveFormat{};
        waveFormat.wFormatTag = WAVE_FORMAT_PCM;
        waveFormat.nChannels = 2; // 双声道
        waveFormat.nSamplesPerSec = 44100; // 采样率
        waveFormat.wBitsPerSample = 16; // 每个样本的位数
        waveFormat.nBlockAlign = (waveFormat.nChannels * waveFormat.wBitsPerSample) / 8;
        waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;

        if (FAILED(primaryBuffer->SetFormat(&waveFormat))) {
            std::cout << "Failed to set primary buffer format" << std::endl;
            return false;
        }

        return true;
    }

    bool LoadAudioData(const char* audioFile) {
        // 打开音频文件
        FILE* file;
        fopen_s(&file, audioFile, "rb");
        if (!file) {
            std::cout << "Failed to open audio file" << std::endl;
            return false;
        }

        // 创建次缓冲区(音频数据将被填充到此缓冲区)
        DSBUFFERDESC bufferDesc{};
        bufferDesc.dwSize = sizeof(DSBUFFERDESC);
        bufferDesc.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS;

        WAVEFORMATEX waveFormat{};

        if (fread(&waveFormat, sizeof(WAVEFORMATEX), 1, file) != 1) {
            fclose(file);
            std::cout << "Failed to read wave format from audio file" << std::endl;
            return false;
        }

        bufferDesc.lpwfxFormat = &waveFormat;

        DWORD bufferSize = BUFFER_SIZE;

        if (FAILED(directSound->CreateSoundBuffer(&bufferDesc, &secondaryBuffer, NULL))) {
            fclose(file);
            std::cout << "Failed to create secondary buffer" << std::endl;
            return false;
        }

        // 锁定次缓冲区,以填充音频数据
        LPVOID audioPtr1 = nullptr;
        DWORD audioSize1 = 0;

        LPVOID audioPtr2 = nullptr;
        DWORD audioSize2 = 0;

        if (FAILED(secondaryBuffer->Lock(0, bufferSize, &audioPtr1, &audioSize1, &audioPtr2, &audioSize2, 0))) {
            fclose(file);
            std::cout << "Failed to lock secondary buffer" << std::endl;
            return false;
        }

        // 将音频数据从文件读取到缓冲区中
        if (fread(audioPtr1, audioSize1, 1, file) != 1) {
            fclose(file);
            std::cout << "Failed to read audio data from file" << std::endl;
            return false;
        }

        // 解锁次缓冲区,使其可被播放
        if (FAILED(secondaryBuffer->Unlock(audioPtr1, audioSize1, audioPtr2, audioSize2))) {
            fclose(file);
            std::cout << "Failed to unlock secondary buffer" << std::endl;
            return false;
        }

        fclose(file);

        return true;
    }

    bool Play() {
        if (!secondaryBuffer)
            return false;

        // 设置播放位置为开始处
        if (FAILED(secondaryBuffer->SetCurrentPosition(0))) {
            std::cout << "Failed to set current position of the secondary buffer" << std::endl;
            return false;   
        }

        // 播放音频
        if (FAILED(secondaryBuffer->Play(0, 0, DSBPLAY_LOOPING))) {
            std::cout << "Failed to play the secondary buffer" << std::endl;
            return false;
        }

        return true;
    }
};

int main() {
    // 创建窗口等初始化操作

    // 创建DirectSound播放器对象
    DirectSoundPlayer player;

    if (!player.Initialize(hWnd)) {
        std::cout << "Failed to initialize DirectSound player" << std::endl;
        return -1;
    }

    if (!player.LoadAudioData("audio.wav")) {
        std::cout << "Failed to load audio data" << std::endl;
        return -1;
    }

    if (!player.Play()) {
        std::cout << "Failed to play audio" << std::endl;
        return -1;
    }

    while (true) {
        // 处理消息循环
    }

    return 0;
}

请注意,这只是一个简单的示例代码,并且缺少错误处理和资源释放。实际应用中需要根据需求进行修改和完善。同时,需要将代码与所使用的DirectSound库链接起来。<br/><br/><br/><p style="color:#CCCCCC;font-size:12px;">内容由零声教学AI助手提供,问题来源于学员提问</p>

回复

举报 使用道具

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