Windows音频编程:Win32 Wave API 的使用
2011-11-01 11:25
543 查看
Windows音频编程:Win32 Wave API 的使用
2011-10-27 10:34
//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;
}
}
2011-10-27 10:34
//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;
}
}
相关文章推荐
- Windows音频编程:Win32 Wave API 的使用
- Windows音频编程:Win32 Wave API 的使用
- 面向对象的Windows编程实战(上)(使用C++和Win32 API)
- Windows下使用C++(Win32SDK)编程无需提权读取硬盘序列号(XP、Win7和Win10都可用)
- 全双工音频播放器在c#中使用waveIn / waveOut api
- 使用Windows混音器MIXER的API开发音频控制面板【参考文章】
- 使用WaveOut API播放WAV音频文件(解决卡顿)
- 在Ruby中方便的调用Win32 API (使用windows-pr和CStruct)
- 一个使用Win32SDK编写Windows GUI程序的教程: "theForger's Win32 API Tutorial"
- Win32 API编程:使用CreateProcess创建新进程
- Win32编程API 基础篇 -- 5.使用资源
- Windows下wave API 音频采集
- 在Ruby中方便的调用Win32 API (使用windows-pr和CStruct)
- Windows下使用Subversion Client API编程环境配置
- 窗口启动特效,使用win32 api
- java高级编程学习如何使用打印服务 API
- VS2015动态库编程之Win32动态库的使用(上)
- Windows客户端开发--使用WMI获取显卡详细信息(win32控制台程序)
- 使用 OpenSSL API 进行安全编程,第 3 部分: 提供安全服务
- VC调用ACM音频编程接口压缩Wave音频