windows下使用waveOut播放音频pcm

目录

一、前言

二、waveOut主要API介绍

三、waveOut播放PCM音频框架

《Windows平台使用waveOut播放PCM数据代码实现》链接:

https://edu.csdn.net/learn/38258/606147?spm=1003.2001.3001.4157

一、前言

       在<windows下directShow音视频采集>一篇文章中就介绍了windows下通过directShow音视频采集的流程。windows下directShow不仅可以对音进行采也可以对音频进行播放,但是directShow使用过程较为复杂,所以本文将介绍windows下使用WAVE播放音频的过程。在微软的官方SDK文档说明中就对WAVE播放音频的API做了详细的介绍,连接为<wave播放音频的API介绍>。

二、waveOut主要API介绍

1、waveOutOpen()

        waveOutOpen函数的详细定义如下,该函数用于打开用于播放音频的输出设备。

MMRESULT waveOutOpen(
  LPHWAVEOUT      phwo,
  UINT            uDeviceID,
  LPCWAVEFORMATEX pwfx,
  DWORD_PTR       dwCallback,
  DWORD_PTR       dwInstance,
  DWORD           fdwOpen
);

     参数是phwo是存放wave音频输出设备的句柄的指针;

     参数uDeviceID是wave设备标识ID,当参数为WAVE_MAPPER时候标识可以播放给定格式的音频数据。

    参数pwfx用于设置要播放的音频数据格式。其结构体类型WAVEFORMATEX定义如下。

typedef struct tWAVEFORMATEX
{
    WORD        wFormatTag;         /* format type */
    WORD        nChannels;          /* number of channels (i.e. mono, stereo...) */
    DWORD       nSamplesPerSec;     /* sample rate */
    DWORD       nAvgBytesPerSec;    /* for buffer estimation */
    WORD        nBlockAlign;        /* block size of data */
    WORD        wBitsPerSample;     /* number of bits per sample of mono data */
    WORD        cbSize;             /* the count in bytes of the size of */
                                    /* extra information (after cbSize) */
} WAVEFORMATEX;

      参数dwCallback用于指定回调的机制;当前支持的回调机制包含如下;

指向回调函数的指针A pointer to a callback function
窗口的句柄A handle to a window
线程标识符A thread identifier
事件的句柄A handle to an event
值为 NULLNULL

     参数dwInstance用于传递给回调机制的用户实例数据。

     参数fdwOpen用于打开设备的标志。其值如下(部分)

Value含义
CALLBACK_EVENTdwCallback 参数是事件句柄。
CALLBACK_FUNCTIONdwCallback 参数是回调过程地址。
CALLBACK_NULL无回调机制。 这是默认设置。
CALLBACK_THREADdwCallback 参数是线程标识符。
CALLBACK_WINDOWdwCallback 参数是窗口句柄。

2、waveOutPrepareHeader()

      waveOutPrepareHeader函数的定义如下,该函数用于准备wave音频数据块以供播放。

MMRESULT waveOutPrepareHeader(
  HWAVEOUT  hwo,
  LPWAVEHDR pwh,
  UINT      cbwh
);

      参数hwo为wave音频输出设备的句柄,即waveOutOpen的第一个参数值。

      参数pwh指向要发送的音频数据。其结构体定义如下。

/* wave data block header */
typedef struct wavehdr_tag {
    LPSTR       lpData;                 /* pointer to locked data buffer */
    DWORD       dwBufferLength;         /* length of data buffer */
    DWORD       dwBytesRecorded;        /* used for input only */
    DWORD_PTR   dwUser;                 /* for client's use */
    DWORD       dwFlags;                /* assorted flags (see defines) */
    DWORD       dwLoops;                /* loop control counter */
    struct wavehdr_tag FAR *lpNext;     /* reserved for driver */
    DWORD_PTR   reserved;               /* reserved for driver */
} WAVEHDR;

       参数cbwh为WAVEHDR 结构的大小,通常取值为sizeof(WAVEHDR)。

3、waveOutWrite()

       waveOutWrite函数的定义如下,该函数用于发送一个数据给音频播放设备。

MMRESULT waveOutWrite(
  HWAVEOUT  hwo,
  LPWAVEHDR pwh,
  UINT      cbwh
);

    参数hwo为wave音频输出设备的句柄,即waveOutOpen的第一个参数值。

    参数pwh指向要发送的音频数据。

    参数cbwh为WAVEHDR 结构的大小,通常取值为sizeof(WAVEHDR)。

  4、除了上诉三个API,在使用wave播放PCM音频还会用到CreateEvent、CloseHandle和WaitForSingleObject函数。CreateEvent用于创建事件。CloseHandle用于关闭事件。WaitForSingleObject用于观察线程信号状态,当线程信号状态为事件则返回;其定义如下

WaitForSingleObject(
    _In_ HANDLE hHandle,
    _In_ DWORD dwMilliseconds
    );

      参数hHandle为CreateEvent创建事件的句柄;

      参数dwMilliseconds为超时等待的参数。

5、waveOutClose(_In_ HWAVEOUT hwo)

     该函数用于关闭已经打开的wave音频播放设备。

     参数hwo为wave音频输出设备的句柄;

三、waveOut播放PCM音频框架

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Windows 平台上,可以使用 Windows API 中的 waveOutOpenwaveOutPrepareHeader、waveOutWrite 等函数来实现播放 PCM 音频的功能。具体步骤如下: 1. 打开音频设备 使用 waveOutOpen 函数打开音频设备,获取一个 HWO(音频输出设备句柄),可以指定音频格式、回调函数等参数。 2. 准备音频数据 使用 waveOutPrepareHeader 函数对音频数据进行预处理,为音频数据分配缓冲区,并将音频数据拷贝到缓冲区中。每个缓冲区都有一个 WAVEHDR 结构体表示,其中包含缓冲区地址、大小、状态等信息。 3. 开始播放音频 使用 waveOutWrite 函数将已经准备好的音频数据缓冲区加入到音频设备的播放队列中。当音频设备播放完一个缓冲区时,会调用回调函数,应用程序可以在回调函数中继续填充数据。 4. 停止播放音频 使用 waveOutReset 函数停止音频设备的播放,并将所有缓冲区从播放队列中移除。使用 waveOutUnprepareHeader 函数释放缓冲区及其相关资源。 以下是一个简单的示例代码,用于播放一个 PCM 音频文件: ```c++ #include <windows.h> #include <mmsystem.h> #include <stdio.h> #pragma comment(lib,"winmm.lib") int main() { HWAVEOUT hwo; WAVEFORMATEX wfx; MMRESULT result; // 打开音频设备 ZeroMemory(&wfx, sizeof(wfx)); wfx.wFormatTag = WAVE_FORMAT_PCM; // PCM 音频格式 wfx.nChannels = 2; // 双声道 wfx.nSamplesPerSec = 44100; // 采样率 wfx.wBitsPerSample = 16; // 量化位数 wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; result = waveOutOpen(&hwo, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL); if (result != MMSYSERR_NOERROR) { printf("Failed to open audio device. Error code: %d\n", result); return 1; } // 打开 PCM 音频文件 FILE* file = fopen("audio.pcm", "rb"); if (file == NULL) { printf("Failed to open audio file.\n"); return 1; } // 循环读取 PCM 数据,并播放 const int BUFFER_SIZE = 4096; char buffer[BUFFER_SIZE]; while (true) { int readSize = fread(buffer, 1, BUFFER_SIZE, file); if (readSize == 0) { break; } WAVEHDR hdr; ZeroMemory(&hdr, sizeof(hdr)); hdr.lpData = buffer; hdr.dwBufferLength = readSize; result = waveOutPrepareHeader(hwo, &hdr, sizeof(hdr)); if (result != MMSYSERR_NOERROR) { printf("Failed to prepare audio header. Error code: %d\n", result); return 1; } result = waveOutWrite(hwo, &hdr, sizeof(hdr)); if (result != MMSYSERR_NOERROR) { printf("Failed to play audio data. Error code: %d\n", result); return 1; } while (hdr.dwFlags & WHDR_PREPARED) { Sleep(10); } } // 关闭音频设备 waveOutReset(hwo); waveOutClose(hwo); fclose(file); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值