直接上代码。假设有须要能够直接建一个win32控制台程序然后将代码拷过去改个文件名称就能够用了(注意将声道和频率与你自己的文件相应)。当然我自己也用VS2008写了个样例上传了,假设有须要下载地址例如以下:点击打开链接。

这份代码是打开文件截取一段数据然后播放的,能够轻松的经过加一条线程的方式改成网络传输的形式,但经过本人測试,由于没有缓存机制会有“哒哒”的噪声,也就是说这份代码在网络实时音频上的表现并不太好。为了解决问题,能够加上缓存机制,本人由于一開始用的是事件响应方式。所以一直困在这个框架里,不能非常好的利用缓存的机制解决上面提到的问题,后来尝试了用回调函数的方式来响应数据播放完毕的消息。问题就轻松的攻克了。

那部分的代码会在稍候放上去。

#include "stdafx.h"
#include <stdio.h>
#include <Windows.h>
#pragma comment(lib, "winmm.lib")char buf[1024 * 1024 * 4];int _tmain(int argc, _TCHAR* argv[]) {FILE*           thbgm;//文件int             cnt;HWAVEOUT        hwo;WAVEHDR         wh;WAVEFORMATEX    wfx;HANDLE          wait;wfx.wFormatTag = WAVE_FORMAT_PCM;//设置波形声音的格式wfx.nChannels = 1;//设置音频文件的通道数量wfx.nSamplesPerSec = 8000;//设置每一个声道播放和记录时的样本频率wfx.nAvgBytesPerSec = 16000;//设置请求的平均传输数据率,单位byte/s。这个值对于创建缓冲大小是非常实用的wfx.nBlockAlign = 2;//以字节为单位设置块对齐wfx.wBitsPerSample = 16;wfx.cbSize = 0;//额外信息的大小wait = CreateEvent(NULL, 0, 0, NULL);waveOutOpen(&hwo, WAVE_MAPPER, &wfx, (DWORD_PTR)wait, 0L, CALLBACK_EVENT);//打开一个给定的波形音频输出装置来进行回放fopen_s(&thbgm, "paomo.pcm", "rb");cnt = fread(buf, sizeof(char), 1024 * 1024 * 4, thbgm);//读取文件4M的数据到内存来进行播放。通过这个部分的改动,添加线程可变成网络音频数据的实时传输。当然假设希望播放完整的音频文件,也是要在这里略微改一改int dolenght = 0;int playsize = 1024;while (cnt) {//这一部分须要特别注意的是在循环回来之后不能花太长的时间去做读取数据之类的工作,不然在每一个循环的间隙会有“哒哒”的噪音wh.lpData = buf + dolenght;wh.dwBufferLength = playsize;wh.dwFlags = 0L;wh.dwLoops = 1L;waveOutPrepareHeader(hwo, &wh, sizeof(WAVEHDR));//准备一个波形数据块用于播放waveOutWrite(hwo, &wh, sizeof(WAVEHDR));//在音频媒体中播放第二个函数wh指定的数据WaitForSingleObject(wait, INFINITE);//用来检測hHandle事件的信号状态,在某一线程中调用该函数时,线程临时挂起,假设在挂起的INFINITE毫秒内。线程所等待的对象变为有信号状态。则该函数马上返回dolenght = dolenght + playsize;cnt = cnt - playsize;}waveOutClose(hwo);fclose(thbgm);return 0;
}

离写上面部分已经过了快一年。如今回看之前写的代码感觉略为坑爹,也许是进步了吧。

之前说要把双缓存的代码放出来。哪知道后来忙别的项目去了,这部分就丢到一边,去老项目中提代替码感觉好烦一直没弄。在这一年中不少人发私信问我关于这部分代码怎样写的事,没想到如今做音频的人还真不少呢。Ok。既然挖了坑就要填,今天乘着周末写了一个双缓存的Demoproject,代码例如以下:

#include <stdio.h>
#include <Windows.h>#pragma comment(lib, "winmm.lib")#define DATASIZE 1024*512 //分次截取数据大小
FILE*           pcmfile;  //音频文件
HWAVEOUT        hwo;void CALLBACK WaveCallback(HWAVEOUT hWave, UINT uMsg, DWORD dwInstance, DWORD dw1, DWORD dw2)//回调函数
{switch (uMsg){case WOM_DONE://上次缓存播放完毕,触发该事件{LPWAVEHDR pWaveHeader = (LPWAVEHDR)dw1;pWaveHeader->dwBufferLength = fread(pWaveHeader->lpData, 1, DATASIZE, pcmfile);;waveOutPrepareHeader(hwo, pWaveHeader, sizeof(WAVEHDR));waveOutWrite(hwo, pWaveHeader, sizeof(WAVEHDR));break;}}
}void main()
{int             cnt;WAVEHDR         wh1;WAVEHDR         wh2;WAVEFORMATEX    wfx;fopen_s(&pcmfile, "paomo.pcm", "rb");//打开文件wfx.wFormatTag = WAVE_FORMAT_PCM;//设置波形声音的格式wfx.nChannels = 1;//设置音频文件的通道数量wfx.nSamplesPerSec = 8000;//设置每一个声道播放和记录时的样本频率wfx.nAvgBytesPerSec = 16000;//设置请求的平均传输数据率,单位byte/s。

这个值对于创建缓冲大小是非常实用的 wfx.nBlockAlign = 2;//以字节为单位设置块对齐 wfx.wBitsPerSample = 16; wfx.cbSize = 0;//额外信息的大小 waveOutOpen(&hwo, WAVE_MAPPER, &wfx, (DWORD)WaveCallback, 0L, CALLBACK_FUNCTION);//打开一个给定的波形音频输出装置来进行声音播放,方式为回调函数方式。假设是对话框程序,能够将第五个參数改为(DWORD)this。操作跟本Demo程序类似 wh1.dwLoops = 0L;//播放区一 wh1.lpData = new char[DATASIZE]; wh1.dwBufferLength = DATASIZE; fread(wh1.lpData, 1, DATASIZE, pcmfile); wh1.dwFlags = 0L; waveOutPrepareHeader(hwo, &wh1, sizeof(WAVEHDR));//准备一个波形数据块用于播放 waveOutWrite(hwo, &wh1, sizeof(WAVEHDR));//在音频媒体中播放第二个參数指定的数据,也相当于开启一个播放区的意思 wh2.dwLoops = 0L;//播放区二,基本同上 wh2.lpData = new char[DATASIZE]; wh2.dwBufferLength = DATASIZE; fread(wh2.lpData, 1, DATASIZE, pcmfile); wh2.dwFlags = 0L; waveOutPrepareHeader(hwo, &wh2, sizeof(WAVEHDR)); waveOutWrite(hwo, &wh2, sizeof(WAVEHDR)); while (wh1.dwBufferLength != 0 || wh2.dwBufferLength != 0)//假设文件还在没播放完则等待500ms { Sleep(500); } waveOutUnprepareHeader(hwo, &wh1, sizeof(WAVEHDR));//清理数据 waveOutUnprepareHeader(hwo, &wh2, sizeof(WAVEHDR)); delete []wh1.lpData; delete []wh2.lpData; fclose(pcmfile);//关闭文件 return; }

同上面一样。假设想要这个project的能够到这个链接去下载。

只是提醒下,本人已然抛弃了VS2008。直接用VS2013,假设还在用老平台的话要用还是要折腾一会的。

C++ 播放音频流(PCM裸流)相关推荐

  1. C++ 採集音频流(PCM裸流)实现录音功能

    与上一篇的"C++ 播放音频流(PCM裸流)" 点击打开链接 相相应,本篇是关于用C++实现录音功能的.相同是直接建一个win32控制台程序然后将代码拷过去改个文件名称就能够用,也 ...

  2. PCM裸流ADPCM算法压缩(调用adpcm_coder/adpcm_decoer接口)

    最近一周做一个ADPCM算法的调研工作,以前是做电视智能浏览器,所以对这个东西不了解,虽然给我了算法的接口, 使用intel的adpcm_coder/adpcm_decoder进行压缩和解压,参数也能 ...

  3. PCM裸流数据的16进制格式以及左右声道分离c语言程序

    前言 本文讲解PCM裸流数据的存储格式. 本文PCM音频参数 声道数: 2采样位数: little endian signed 16 bits,小端有符号字 = short,表示范围 -32768~3 ...

  4. 成功在MP4封装的H264视频中提取能播放的裸流

    首先说明一下,本人只是从MP4(AVC)封装的h264视频流中成功把裸流提取出来并进行播放,而这一段MP4封装的流中是不含音频流的,因为项目并不需要实现这个,所以我也就偷懒了,需要从含有音频流的MP4 ...

  5. FFmpeg系列(二)—— 音视频裸流转换:mp3转pcm、h264转YUV

    文章目录 1.总流程 2.解析流程 3.解码流程 4.完整代码 1.总流程 创建解析器.解码器.AVPacket和AVFrame 打开文件,将mp3数据读入缓冲区 解析mp3数据(在 main 函数中 ...

  6. 【FFmpeg】ffplay 播放视频命令 ( 播放 | 暂停 | 停止 | 音量控制 | 进度控制 | 音频流 / 视频流 / 字幕流 / 节目切换 )

    FFmpeg 系列文章目录 [FFmpeg]Windows 搭建 FFmpeg 命令行运行环境 [FFmpeg]FFmpeg 相关术语简介 ( 容器 | 媒体流 | 数据帧 | 数据包 | 编解码器 ...

  7. Android Socket 连接设备接收H264裸流数据并解码播放 Demo

    最近在做视频流相关的项目,发现 网上很少这方面的demo,很多都是长篇大论的理论知识,研究的太深,不利于小白快速 上手.所以我提炼了自己项目中这一块的内容,打包个小 demo ,只要 拿去稍作修改基本 ...

  8. h264 裸流打包成mp4 注意事项

    需求: Android 端把网络摄像头的一段正在播放的视频流,截取保存成mp4(按录像按钮时开始录像). 实现: ffmpeg + x264 + sdl; h264 裸流 打包成MP4,在网上也有一大 ...

  9. RTSP再学习 -- 利用FFmpeg 将 rtsp 获取H264裸流并保存到文件中

    如需转载请注明出处:https://blog.csdn.net/qq_29350001/article/details/78214267 既然已经可以通过 RTSP 获取h264 裸流了.那么通过 F ...

最新文章

  1. android4.4 添加快捷开关(以截屏为例)
  2. vsftp安装与配置(通过虚拟用户登录)
  3. Swagger-概述
  4. Lucene之Java实战
  5. java 模型 视图,部分视图模型
  6. 一个Java多线程练习的调试
  7. 将二进制文件bold转化为文件file
  8. DNS高可用设计--软件高可用
  9. Qt QComboBox详解
  10. 三星内存编码_想问一下三星内存条的型号有什么区别
  11. 双击事件(dblclick)时,不触发单击事件(click)
  12. hud抬头显示器哪个好_什么样的HUD抬头显示器好?圆盾用是实力说话
  13. 中国十大垃圾软件网站
  14. 你永远不知道明天和意外哪个先到来
  15. GBase 8s Java UDR安装说明
  16. Date类的getDay()和getDate()方法
  17. 今日金融词汇---预收,是什么?
  18. 谷歌的合纵贯通:互联网、通信和节能领域
  19. 阿里云服务器配置(四)
  20. 威武山上的分配-计蒜客

热门文章

  1. Android 音视频开发入门指南
  2. Almost sorted interval
  3. Spring学习篇:IoC知识整理(一)
  4. 西霞口船业公司疑遭外商合谋欺诈
  5. install openstack on single host
  6. 华硕服务器第三届“IT硬件平台搭建大赛”获奖方案
  7. 英特尔未来教育核心课程
  8. 网络安全 — 安全架构
  9. Openstack nova-scheduler 源码分析 — Filters/Weighting
  10. matlab-高数 find 找到集合中特定元素的位置