本人擅长C#开发,pcm播放本来想用C#实现,但是考虑到视频的解码使用C++做的,于是用C++实现了pcm的播放。这里使用微软的directsound库。

第一步:

读取一个pcm文件

 FILE * InFile;InFile = fopen("testu.pcm", "rb");

此文件为单通道,8000采样率,16bit每次采样。

第二步:

定期读取pcm文件,每次读取一秒的数据:iChannel*SampleRate*2 这里大小为1*8000*2 =16000

 while (true){int iReadSize = fread(frame_buf, 1, iChannel*SampleRate*2, InFile);if (iReadSize>0){pcmPlay.PushData(frame_buf, iReadSize);}else{break;}Sleep(1000);}

第三步:

初始化directsound相关变量:

 m_iBufNofitySize = sample_rate*channels;offset = m_iBufNofitySize;m_Audiobuf = new char[m_iBufNofitySize * 10];//Init DirectSoundif (FAILED(DirectSoundCreate8(NULL, &m_pDS, NULL))){return false;}SetConsoleTitle(TEXT("pcmplayer"));//Console Titleif (FAILED(m_pDS->SetCooperativeLevel(FindWindow(NULL, TEXT("pcmplayer")), DSSCL_NORMAL)))return FALSE;DSBUFFERDESC dsbd;memset(&dsbd, 0, sizeof(dsbd));dsbd.dwSize = sizeof(dsbd);dsbd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2;dsbd.dwBufferBytes = MAX_AUDIO_BUF * m_iBufNofitySize;dsbd.lpwfxFormat = (WAVEFORMATEX*)malloc(sizeof(WAVEFORMATEX));dsbd.lpwfxFormat->wFormatTag = WAVE_FORMAT_PCM;/* format type */(dsbd.lpwfxFormat)->nChannels = channels;/* number of channels (i.e. mono, stereo...) */(dsbd.lpwfxFormat)->nSamplesPerSec = sample_rate;/* sample rate */(dsbd.lpwfxFormat)->nAvgBytesPerSec = sample_rate * (bits_per_sample / 8)*channels;/* for buffer estimation */(dsbd.lpwfxFormat)->nBlockAlign = (bits_per_sample / 8)*channels;/* block size of data */(dsbd.lpwfxFormat)->wBitsPerSample = bits_per_sample;/* number of bits per sample of mono data */(dsbd.lpwfxFormat)->cbSize = 0;if (FAILED(m_pDS->CreateSoundBuffer(&dsbd, &m_pDSBuffer, NULL))) {return false;}if (FAILED(m_pDSBuffer->QueryInterface(IID_IDirectSoundBuffer8, (LPVOID*)&m_pDSBuffer8))) {return false;}//Get IDirectSoundNotify8if (FAILED(m_pDSBuffer8->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&m_pDSNotify))) {return false;}for (int i = 0; i<MAX_AUDIO_BUF; i++) {m_pDSPosNotify[i].dwOffset = i * m_iBufNofitySize;m_event[i] = ::CreateEvent(NULL, false, false, NULL);m_pDSPosNotify[i].hEventNotify = m_event[i];}m_pDSNotify->SetNotificationPositions(MAX_AUDIO_BUF, m_pDSPosNotify);m_pDSNotify->Release();m_pDSBuffer8->SetCurrentPosition(0);m_pDSBuffer8->Play(0, 0, DSBPLAY_LOOPING);

第五步:开启一个线程,定期去读取数据,并放入directsound缓存进行播放

 LPVOID buf = NULL;DWORD  buf_len = 0;if ((res >= WAIT_OBJECT_0) && (res <= WAIT_OBJECT_0 + 3)) {m_pDSBuffer8->Lock(offset, m_iBufNofitySize, &buf, &buf_len, NULL, NULL, 0);if (m_iAudioLenth > m_iBufNofitySize){AutoLock lock(m_bufLock);memcpy(buf, m_Audiobuf, m_iBufNofitySize);m_iAudioLenth = m_iAudioLenth - m_iBufNofitySize;memcpy(m_Audiobuf, m_Audiobuf + m_iBufNofitySize, m_iAudioLenth);}else{memset(buf, 0, m_iBufNofitySize);}offset += buf_len;offset %= (m_iBufNofitySize * MAX_AUDIO_BUF);//printf("this is %7d of buffer\n", offset);m_pDSBuffer8->Unlock(buf, buf_len, NULL, 0);}res = WaitForMultipleObjects(MAX_AUDIO_BUF, m_event, FALSE, INFINITE);return 1;

第六步:

播放结束后,释放相关内容。

这里,主要讲一下directsound的播放原理。

首先我们要这只播放缓存:

dsbd.dwBufferBytes = MAX_AUDIO_BUF * m_iBufNofitySize;

但是我们如何知道这段音频播放完了呢?我们可以设置一个通知大小,即播放完多大空间,就通知一次。然后我们就把这段播放完的空间,用新的音频数据进行填充,由于directsound是在指定空间循环播放的,我们也就可以实现音频的循环播放。

音频1 音频2 音频3 音频4

directsound播放顺序为音频1---》音频2---》音频3---》音频4---》音频1 每一段播放完,就会通知一次。

另外,需要提醒播放缓存不能设置太小,会没有播放效果,不过设置过大,延迟又比较大,所以我把每一段缓存这只为1秒左右的空间。

为了便于大家学习和交流,采用vs2017开发,地址如下:

https://download.csdn.net/download/g0415shenw/10620701

directsound之播放pcm相关推荐

  1. 最简单的视音频播放示例8:DirectSound播放PCM

    ===================================================== 最简单的视音频播放示例系列文章列表: 最简单的视音频播放示例1:总述 最简单的视音频播放示例 ...

  2. DirectSound播放PCM有杂音的解决方法

    问题场景描述:使用DirectSound播放PCM,先点击暂停按钮再点击播放按钮后,大概率会有杂音出现 播放音频单独放在一个线程中处理,程序基于MFC架构,有播放和暂停按钮.如下所示代码为音频播放线程 ...

  3. DirectSound播放PCM(可播放实时采集的音频数据)

    前言 该篇整理的原始来源为http://blog.csdn.net/leixiaohua1020/article/details/40540147.非常感谢该博主的无私奉献,写了不少关于不同多媒体库的 ...

  4. 最简单的视音频播放示例9:SDL2播放PCM

    本文记录SDL播放音频的技术.在这里使用的版本是SDL2.实际上SDL本身并不提供视音频播放的功能,它只是封装了视音频播放的底层API.在Windows平台下,SDL封装了Direct3D这类的API ...

  5. C# DirectX.DirectSound声音播放

    英文原文:https://msdn.microsoft.com/en-us/library/windows/desktop/bb318665(v=vs.85).aspx Microsoft Direc ...

  6. php nsdata,iOS播放PCM,NSData流代码(Audio Queue Services)

    2019-12-28: 已归档,代码不保证可用 最近有需求从蓝牙接收音频数据进行播放,把一些东西记录下来,顺带希望可以帮到你 然后这里是用的是Audio Queue Services,只能用于PCM数 ...

  7. Android开发之PCM录音实时播放的实现方法 | 边录音边播放 |PCM录音播放无延迟 | 录音无杂音 | 录音无噪音

    先说下录音得开启录音权限 <uses-permission android:name="android.permission.RECORD_AUDIO" /> 然后录音 ...

  8. java 播放.pcm文件,java播发PCM文件

    java播放PCM文件 import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundExceptio ...

  9. AudioTrack 播放PCM音频数据

    AudioTrack 可以用来播放PCM数据,上一篇博客我讲了AudioRecord可以录制PCM数据 AudioTrack实例可以在两种模式下运行:静态或流式传输. 在Streaming模式下,应用 ...

最新文章

  1. GitHub趋势榜第一:超强PyTorch目标检测库Detectron2,训练更快,支持更多任务
  2. linux下利用valgrind工具进行内存泄露检测和性能分析
  3. 非对称加密 公钥私钥_选择Java加密算法第3部分–公钥/私钥非对称加密
  4. n.html id=198,YPE htmlhtml lang=enhead data-n-head-ssrtitle data-n-=true小程序获取不到unionid 微信开放社区...
  5. linux安装.AppImage后缀安装包
  6. UITextField加间隔符号格式化
  7. GS3D An Efficient 3D Object Detection Framework for Autonomous Driving算法解析
  8. 英语翻译软件测试简历,如此翻译-2 - Victor's Testing Career - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...
  9. php计算时间差js,JS计算日期时间差
  10. 大数据时代的教育宏观治理体制现代化变革
  11. 如何让mysql数据库支持超大图片
  12. input 标签的属性class是什么作用?
  13. 入门3D建模学习教程,让你最快从小白到建模大师!
  14. *item_search_similar - 搜索相似的商品**
  15. org.apache.flink.util.FlinkRuntimeException: Exceeded checkpoint tolerable failure threshold
  16. 对学姐的U-net网络的学习杂记
  17. OSChina 周四乱弹 ——印象开源中国:总是飙车就容易脱发
  18. STM32开发板串口 ISP 方式下载程序
  19. IDEA导入Mybatis源码
  20. 查找IT行业报告网站

热门文章

  1. win7做wifi服务器
  2. 详细讲解怎样做数据仓库需求分析
  3. GCC 11.1 进行 C++ 多项优化
  4. 开源bot工具Rasa学习---1
  5. 单片机的各种存储的含义和区别
  6. linux使用---automake学习(从原理到实践,一步步完成automake)
  7. 集成学习的前世今生(一)
  8. 察看无限网络linux,linux 无线网络调试
  9. python创建文件对象的函数_Python学习笔记之—— File(文件) 对象常用函数
  10. 三星w609 java_完美复刻叫板三星W2019,这款商务手机有点牛