//Windows音频编程:Win32 Wave API 的使用

//下面是一个Win32控制台程序的源码,环境VS2008,新建一个空的Win32控制台项目,加入此文件编译即可,功能为录制5秒并回放。注意不要选择Unicode字符集,不然设备名会出现乱码。
//  
//  WaveAPI.cpp  
//  
// by: 知秋一叶  
//  
// 转载:http://blog.csdn.net/zhi_qiu_yi_ye/article/details/6663366

#include <windows.h>  
#include <stdio.h>  
#include <mmsystem.h>  
#pragma comment(lib, "winmm.lib")

#define BUFFER_SIZE (44100*16*2/8*5)    // 录制声音长度  
#define FRAGMENT_SIZE 1024              // 缓存区大小  
#define FRAGMENT_NUM 4                  // 缓存区个数

static unsigned char buffer[BUFFER_SIZE] = {0};  
static int buf_count = 0;

// 函数定义  
void CALLBACK waveInProc(HWAVEIN hwi,        
                        UINT uMsg,          
                        DWORD_PTR dwInstance,    
                        DWORD_PTR dwParam1,    
                        DWORD_PTR dwParam2     );  
void CALLBACK waveOutProc(  HWAVEOUT hwo,    
                         UINT uMsg,          
                         DWORD_PTR dwInstance,    
                         DWORD_PTR dwParam1,      
                         DWORD_PTR dwParam2     );

// 入口  
int main()  
{  
   /* 录音 */

// Device  
   int nReturn = waveInGetNumDevs();  
   printf("输入设备数目:%d\n", nReturn);  
   for (int i=0; i<nReturn; i++)  
   {  
       WAVEINCAPS wic;  
       waveInGetDevCaps(i, &wic, sizeof(WAVEINCAPS));  
       printf("#%d\t设备名:%s\n", i, wic.szPname);  
   }

// open  
   HWAVEIN hWaveIn;  
   WAVEFORMATEX wavform;  
   wavform.wFormatTag = WAVE_FORMAT_PCM;  
   wavform.nChannels = 2;  
   wavform.nSamplesPerSec = 44100;  
   wavform.nAvgBytesPerSec = 44100*16*2/8;  
   wavform.nBlockAlign = 4;  
   wavform.wBitsPerSample = 16;  
   wavform.cbSize = 0;

waveInOpen(&hWaveIn, WAVE_MAPPER, &wavform, (DWORD_PTR)waveInProc, 0, CALLBACK_FUNCTION);

WAVEINCAPS wic;  
   waveInGetDevCaps((UINT_PTR)hWaveIn, &wic, sizeof(WAVEINCAPS));  
   printf("打开的输入设备:%s\n", wic.szPname);

// prepare buffer  
   static WAVEHDR wh[FRAGMENT_NUM];  
   for (int i=0; i<FRAGMENT_NUM; i++)  
   {  
       wh[i].lpData = new char[FRAGMENT_SIZE];  
       wh[i].dwBufferLength = FRAGMENT_SIZE;  
       wh[i].dwBytesRecorded = 0;  
       wh[i].dwUser = NULL;  
       wh[i].dwFlags = 0;  
       wh[i].dwLoops = 1;  
       wh[i].lpNext = NULL;  
       wh[i].reserved = 0;

waveInPrepareHeader(hWaveIn, &wh[i], sizeof(WAVEHDR));  
       waveInAddBuffer(hWaveIn, &wh[i], sizeof(WAVEHDR));  
   }

// record  
   printf("Start to Record...\n");

buf_count = 0;  
   waveInStart(hWaveIn);

while (buf_count < BUFFER_SIZE)  
   {  
       Sleep(1);  
   }

printf("Record Over!\n\n");

// clean  
   waveInStop(hWaveIn);  
   waveInReset(hWaveIn);  
   for (int i=0; i<FRAGMENT_NUM; i++)  
   {  
       waveInUnprepareHeader(hWaveIn, &wh[i], sizeof(WAVEHDR));  
       delete wh[i].lpData;  
   }  
   waveInClose(hWaveIn);

system("pause");  
   printf("\n");

/* 放音 */

// Device  
   nReturn = waveOutGetNumDevs();  
   printf("\n输出设备数目:%d\n", nReturn);  
   for (int i=0; i<nReturn; i++)  
   {  
       WAVEOUTCAPS woc;  
       waveOutGetDevCaps(i, &woc, sizeof(WAVEOUTCAPS));  
       printf("#%d\t设备名:%s\n", i, wic.szPname);  
   }

// open  
   HWAVEOUT hWaveOut;  
   waveOutOpen(&hWaveOut, WAVE_MAPPER, &wavform, (DWORD_PTR)waveOutProc, 0, CALLBACK_FUNCTION);

WAVEOUTCAPS woc;  
   waveOutGetDevCaps((UINT_PTR)hWaveOut, &woc, sizeof(WAVEOUTCAPS));  
   printf("打开的输出设备:%s\n", wic.szPname);

// prepare buffer  
   WAVEHDR wavhdr;  
   wavhdr.lpData = (LPSTR)buffer;  
   wavhdr.dwBufferLength = BUFFER_SIZE;  
   wavhdr.dwFlags = 0;  
   wavhdr.dwLoops = 0;

waveOutPrepareHeader(hWaveOut, &wavhdr, sizeof(WAVEHDR));

// play  
   printf("Start to Play...\n");

buf_count = 0;  
   waveOutWrite(hWaveOut, &wavhdr, sizeof(WAVEHDR));  
   while (buf_count < BUFFER_SIZE)  
   {  
       Sleep(1);  
   }

// clean  
   waveOutReset(hWaveOut);  
   waveOutUnprepareHeader(hWaveOut, &wavhdr, sizeof(WAVEHDR));  
   waveOutClose(hWaveOut);

printf("Play Over!\n\n");

return 0;  
}

// 录音回调函数  
void CALLBACK waveInProc(HWAVEIN hwi,        
                        UINT uMsg,          
                        DWORD_PTR dwInstance,    
                        DWORD_PTR dwParam1,    
                        DWORD_PTR dwParam2     )  
{  
   LPWAVEHDR pwh = (LPWAVEHDR)dwParam1;

if ((WIM_DATA==uMsg) && (buf_count<BUFFER_SIZE))  
   {  
       int temp = BUFFER_SIZE - buf_count;  
       temp = (temp>pwh->dwBytesRecorded) ? pwh->dwBytesRecorded : temp;  
       memcpy(buffer+buf_count, pwh->lpData, temp);  
       buf_count += temp;

waveInAddBuffer(hwi, pwh, sizeof(WAVEHDR));  
   }  
}

// 放音回调函数  
void CALLBACK waveOutProc(  HWAVEOUT hwo,    
                         UINT uMsg,          
                         DWORD_PTR dwInstance,    
                         DWORD_PTR dwParam1,      
                         DWORD_PTR dwParam2     )  
{  
   if (WOM_DONE == uMsg)  
   {  
       buf_count = BUFFER_SIZE;  
   }  
}

转载于:https://blog.51cto.com/2339637/1354925

Windows音频编程:Win32 Wave API 的使用相关推荐

  1. windows 音频编程

    windows 音频编程主要有三种方式: 1.MCI,这种方式很简单,但是不够灵活  2.waveXXXX等低阶的声音API  3.DirectSound 编写一个功能较强大的音频处理程序,那就必须使 ...

  2. Windows Mobile 编程 (Win32) - 获取设备能力

    <Windows 程序设计>第五章重点讲述图形基础.首先一个示例代码是获取设备描述表信息.代码与Windows Mobile 编程 (Win32) - 输出文本中的代码类似. #inclu ...

  3. Windows SDK编程 API入门系列(转)

    之一 -那'烦人'的Windows数据类型 原创文章,转载请注明作者及出处. 首发 http://blog.csdn.net/beyondcode http://www.cnblogs.com/bey ...

  4. 插入DLL和挂接API——Windows核心编程学习手札之二十二

    插入DLL和挂接API --Windows核心编程学习手札之二十二 如下情况,可能要打破进程的界限,访问另一个进程的地址空间: 1)为另一个进程创建的窗口建立子类时: 2)需要调试帮助时,如需要确定另 ...

  5. Windows界面编程_Miniblink(2) 嵌入到Win32窗口里

    这里博主不教关于Miniblink其它功能,只教对UI界面编程相关的API! 第一步如何在Win32的窗口里嵌入Miniblink? 第一步先创建一个Win32工程 第二步包含wke头文件: #inc ...

  6. Windows核心编程 - API HOOK应用

    #Windows核心编程 - API HOOK应用 如需转载请标明出处:http://blog.csdn.net/itas109 QQ技术交流群:129518033 目录 文章目录 #Windows核 ...

  7. windows下实现win32俄罗斯方块练手,编程的几点心得

    编程珠玑2阅读笔记: 1.使用c语言性能监视器,完成对代码的调优工作 2.关联数组:  拓扑排序算法,可以用于当存在遮挡的时候决定三维场景的绘制顺序. 3.小型算法中的测试与调试工具 脚手架程序:&l ...

  8. 2、从汇编语言到Windows内核编程笔记(2)

    内核线程 在驱动中生成的线程一般是系统线程.系统线程所在的进程名为"System". NTSTATUS PsCreateSystemThread( OUT PHANDLE Thre ...

  9. [转]Windows CE 编程的十点忠告(by pdasky)

    最近两周我们花了大部分时间将已有的应用程序移植到Microsoft Windows CE中.一般说来,这个计划不是太难.我们起步于Microsoft Win32代码,当然 Windows CE是基于W ...

最新文章

  1. mac redis 链接_在Ubunt/Mac系统安装Redis以及设置Redis密码并且允许远程连接 - Laravel学习网...
  2. 同期及上期数据对比处理示例.sql
  3. Kaggle 入门练习 -- Titanic
  4. 树莓派3 kali linux很卡,树莓派3装kali Linux 成功写入 但是点不亮 为什么?
  5. 经常和电脑、信息化设备打交道,食品保健养生非常重要!
  6. Android 系统(219)---Android O上networkAttributes的说明
  7. Android 8.0学习(27)--- SystemUI(二)启动流程和初始化
  8. 基于Ubuntu Server 16.04 LTS版本安装和部署Django之(二):Apache安装和配置
  9. 虚拟机安装VMware ESXi 6.7安装过程介绍
  10. Java 集合系列18之 Iterator和Enumeration比较
  11. vue引入阿里云图标
  12. Oracle查询被锁表和解锁方法
  13. VxWorks的漏洞分析与解决方案
  14. [Jetson TX2] NVIDIA Jetson TX2 参数介绍
  15. 数据库kettle,datax,DBMigration,RazorSQL几款迁移工具使用感受(以及如何迁移表的结构如主键,索引,约束等)
  16. 计算机图形学学习:GAMES101
  17. 马士兵网络安全大师班薪选课程
  18. 系统渗透与防护——网络安全
  19. 2021-4-19课程——第5章例题【续】触发器+存储过程和函数
  20. tableau数据分析实战:明星艺人数据分析

热门文章

  1. c svchost 服务 dll_小机巧丨如何解决svchost一直占用网速和内存?
  2. java web前端邮件,javaweb之javamail
  3. mysql第四步安装失败_MySQL8.0版本的安装以及解决安装后MySQL服务无法启动的问题...
  4. Java SpringBoot 页面渲染
  5. Java Servlet request
  6. numpy.core.defchararray.join
  7. 2021年量子计算机奖,中兴通讯携手中国移动共获“2021年未来网络领先创新科技成果”奖...
  8. java程序员内功_Java程序员如何成为内功深厚的架构师
  9. go数据结构与算法| 稀疏数组
  10. 基于VMware vSphere的虚拟化平台,内存分配是如何实现的?