测控 1602 DEV C ++ 环境下 控制台应用程序 善解人意 成员:王帅、赵永玻、侯雅茹
附件:测控 1602 DEV C ++ 环境下 控制台应用程序 源代码 E 组 善解人意
成员:王帅、赵永玻、侯雅茹
注意 ;程序运行环境 DEV C++ 5.8.3
创建 Console Application
选择 “工具”——“编译器选项”
在修改软件参数时,不要把原来的数据删除
用空格隔开
输入 -lwinmm
即可支持 vc++6.0 的运行库
如果运行不成功,可在安装 vc++6.0 后重试。
#include
#include
#include
#include
#include
1
测控 1602 DEV C ++ 环境下 控制台应用程序 善解人意 成员:王帅、赵永玻、侯雅茹
#include
#include "mmsystem.h"
#pragma comment(lib, "winmm.lib")
void WaveInitFormat(LPWAVEFORMATEX m_WaveFormat, WORD nCh, DWORD nSampleRate,
WORD BitsPerSample);
DWORD CALLBACK MicCallback(HWAVEIN hwavein, UINT uMsg, DWORD dwInstance, DWORD
dwParam1, DWORD dwParam2);
void RecordWave();
int simplest_pcm16le_to_wave(const char *pcmpath, int channels, int sample_rate, const char
*wavepath);
void creat_file();
//输入设备句柄
HWAVEIN phwi;
WAVEHDR pwh1; //缓冲区 1
WAVEHDR pwh2;//缓冲区 2
WAVEHDR pwh3;//缓冲区 3
int stop = 0;
FILE *fp1;
//设置停止标记
//指向存储音频数据的文件指针
typedef struct _WAVFORMAT_
{
char ChunkID[4];
uint32_t ChunkSize;
char Format[4];
char Subchunk1ID[4];
uint32_t Subchunk1Size;
uint16_t AudioFormat;
uint16_t NumChannels;
uint32_t SampleRate;
uint32_t ByteRate;
uint16_t BlockAlign;
uint16_t BitsPerSample;
char Subchunk2ID[4];
uint32_t Subchunk2Size;
} WAVFORMAT;
int main()
{
//新建文件,原文件数据被删除
creat_file();
RecordWave();
simplest_pcm16le_to_wave("NocturneNo2inEflat_44.1k_s16le.pcm",
//录音函数
"output_nocture.wav"); //将二进制录音信息从内存中提取,并生成 wav 文件
1,
44100,
2
测控 1602 DEV C ++ 环境下 控制台应用程序 善解人意 成员:王帅、赵永玻、侯雅茹
return 0;
}
void RecordWave()
{
int count = waveInGetNumDevs();
printf("\n 音频输入数量:%d\n", count);
//检测录音设备
WAVEINCAPS waveIncaps;
MMRESULT mmResult = waveInGetDevCaps(0, &waveIncaps, sizeof(WAVEINCAPS));
printf("\n 音频输入设备:%s\n", waveIncaps.szPname);
if (MMSYSERR_NOERROR == mmResult)
{
//HWAVEIN phwi;
WAVEFORMATEX pwfx;
WaveInitFormat
(&pwfx,
//录音格式指针
//波形声音的格式,单声道双声道使用 WAVE_FORMAT_PCM.当包含在
WAVEFORMATEXTENSIBLE 结构中时,使用 WAVE_FORMAT_EXTENSIBLE
1,
44100,
16
//声道数量
//采样率
// 采样位数
);
printf("\n 正在打开音频输入设备");
printf("\n 采样参数:声道 44.1kHz 16bit\n");
mmResult = waveInOpen(
&phwi,
WAVE_MAPPER,
&pwfx,
(DWORD)(MicCallback),
NULL,
CALLBACK_FUNCTION
);//3
if (MMSYSERR_NOERROR == mmResult)
{
//WAVEHDR pwh1;
char buffer1[10240];
pwh1.lpData = buffer1;
pwh1.dwBufferLength = 10240;
pwh1.dwUser = 1;
pwh1.dwFlags = 0;
3
测控 1602 DEV C ++ 环境下 控制台应用程序 善解人意 成员:王帅、赵永玻、侯雅茹
mmResult = waveInPrepareHeader(phwi, &pwh1, sizeof(WAVEHDR));// 为 波 形 输
入设备准备缓冲区
printf("\n 准备缓冲区 1");
//WAVEHDR pwh2;
char buffer2[10240];
pwh2.lpData = buffer2;
pwh2.dwBufferLength = 10240;
pwh2.dwUser = 2;
pwh2.dwFlags = 0;
mmResult = waveInPrepareHeader(phwi, &pwh2, sizeof(WAVEHDR));// 为 波 形 输
入设备准备缓冲区
printf("\n 准备缓冲区 2\n");
// WAVEHDR pwh3;
char buffer3[10240];
pwh3.lpData = buffer3;
pwh3.dwBufferLength = 10240;
pwh3.dwUser = 3;
pwh3.dwFlags = 0;
mmResult = waveInPrepareHeader(phwi, &pwh3, sizeof(WAVEHDR));// 为 波 形 输
入设备准备缓冲区
printf("准备缓冲区 3\n");
if (MMSYSERR_NOERROR == mmResult)
{
mmResult = waveInAddBuffer(phwi, &pwh1, sizeof(WAVEHDR));// 给 输 入 设
printf("\n 将缓冲区 1 加入音频输入设备");
mmResult = waveInAddBuffer(phwi, &pwh2, sizeof(WAVEHDR));// 给 输 入 设
printf("\n 将缓冲区 2 加入音频输入设备\n");
mmResult = waveInAddBuffer(phwi, &pwh3, sizeof(WAVEHDR));// 给 输 入 设
备增加一个缓存
备增加一个缓存
备增加一个缓存
printf("将缓冲区 3 加入音频输入设备\n");
if (MMSYSERR_NOERROR == mmResult)
{
mmResult = waveInStart(phwi);//开始录音
printf("\n 开始录音\n");
Sleep(3500);
}
4
测控 1602 DEV C ++ 环境下 控制台应用程序 善解人意 成员:王帅、赵永玻、侯雅茹
waveInStop(phwi);//停止录音
printf("录音结束\n");
stop = 1;
//
waveInReset(phwi);//复位
// waveInUnprepareHeader(phwi, &pwh1, sizeof(WAVEHDR));//清除缓存,
在准备缓冲区的时候会调用 waveInPrepareHeader 函数,这个函数调用后,为其分配的内存
就无法通过 delete 或者 free 来释放了,因为在该函数调用后这块内存区域被锁定了。此时
必须调用 waveInUnprepareHeader 函数才能解锁定,然后才能释放。
//
//
//
waveInUnprepareHeader(phwi, &pwh2, sizeof(WAVEHDR));
free(&pwh1);
free(&pwh2);
waveInClose(phwi);//关闭录音设备
fclose(fp1);
printf("关闭录音设备\n");
printf("\n 录音信息提取:\n");
get_message() ;
}
}
}
}
void creat_file()
{
if ((fp1 = fopen("E:\\shuai_file.dat", "wb+")) == NULL)
{
//打开可读写的二进制文件
printf("shuai_file 打开失败!\a\n");
exit(0);
}
rewind(fp1);
}
//回调函数
DWORD CALLBACK MicCallback(HWAVEIN hwavein, UINT uMsg, DWORD dwInstance, DWORD
dwParam1, DWORD dwParam2)
{
switch (uMsg)
{
case WIM_OPEN:
//打开设备时消息,在此期间进行一些初始化工作
5
测控 1602 DEV C ++ 环境下 控制台应用程序 善解人意 成员:王帅、赵永玻、侯雅茹
printf("\n 设备已经打开...\n");
break;
case WIM_DATA:
//当缓存已满或者停止录音时的消息,处理这个消息可以对缓存进行
重新分配,实现不限长度录音
printf("\n 正在读取缓冲区%d...\n", ((LPWAVEHDR)dwParam1)->dwUser);
if (1 == ((LPWAVEHDR)dwParam1)->dwUser)
{
int iWlened = fwrite(pwh1.lpData, 1, pwh1.dwBytesRecorded, fp1);
fflush(fp1);
}
if (2 == ((LPWAVEHDR)dwParam1)->dwUser)
{
int iWlened = fwrite(pwh2.lpData, 1, pwh2.dwBytesRecorded, fp1);
fflush(fp1);
}
if (3 == ((LPWAVEHDR)dwParam1)->dwUser)
{
int iWlened = fwrite(pwh3.lpData, 1, pwh3.dwBytesRecorded, fp1);
fflush(fp1);
}
waveInAddBuffer(hwavein, (LPWAVEHDR)dwParam1, sizeof(WAVEHDR));
//给输入设
备增加一个缓存
break;
case WIM_CLOSE:
//关闭录音设备时的消息。
printf("\n 设备已经关闭...\n");
break;
default:
break;
}
return 0;
}
void WaveInitFormat(LPWAVEFORMATEX m_WaveFormat, WORD nCh, DWORD nSampleRate,
WORD BitsPerSample)
{
//录音文件初始化设置
m_WaveFormat->wFormatTag = WAVE_FORMAT_PCM;
// 数 据 格 式 , 为
WAVE_FORMAT_PCM 即脉冲编码
6
测控 1602 DEV C ++ 环境下 控制台应用程序 善解人意 成员:王帅、赵永玻、侯雅茹
m_WaveFormat->nChannels = nCh;
m_WaveFormat->nSamplesPerSec = nSampleRate;// //采样频率
m_WaveFormat->nAvgBytesPerSec = nSampleRate * nCh * BitsPerSample / 8;
//声道数
//每秒采样
数据量
m_WaveFormat->nBlockAlign = nCh * BitsPerSample / 8;
m_WaveFormat->wBitsPerSample = BitsPerSample;
m_WaveFormat->cbSize = 0;
//样本大小
}
int simplest_pcm16le_to_wave(const char *pcmpath, int channels, int sample_rate, const char
*wavepath)
{
typedef struct WAVE_HEADER {
fccID[4];
char
unsigned long dwSize;
char
fccType[4];
//内容为""RIFF
//最后填写,WAVE 格式音频的大小
//内容为"WAVE"
}WAVE_HEADER;
typedef struct WAVE_FMT {
//内容为"fmt "
//内容为 WAVE_FMT 占的字节数,为 16
fccID[4];
char
unsigned long dwSize;
unsigned short wFormatTag; //如果为 PCM,改值为 1
unsigned short wChannels;
unsigned long dwSamplesPerSec;//采用频率
unsigned
//通道数,单通道=1,双通道=2
long
dwAvgBytesPerSec;/*
==dwSamplesPerSec*wChannels*uiBitsPerSample/8 */
unsigned short wBlockAlign;//==wChannels*uiBitsPerSample/8
unsigned short uiBitsPerSample;//每个采样点的 bit 数,8bits=8, 16bits=16
}WAVE_FMT;
typedef struct WAVE_DATA
{
fccID[4];
char
unsigned long dwSize;
//内容为"data"
//==NumSamples*wChannels*uiBitsPerSample/8
}WAVE_DATA;
if (channels != 1 || sample_rate != 44100)
{
channels = 1;
sample_rate = 44100;
}
int bits = 16;
7
测控 1602 DEV C ++ 环境下 控制台应用程序 善解人意 成员:王帅、赵永玻、侯雅茹
WAVE_HEADER pcmHEADER;
WAVE_FMT
WAVE_DATA
pcmFMT;
pcmDATA;
unsigned short m_pcmData;
FILE *fp, *fpout;
fp = fopen("E:\\shuai_file.dat", "rb");
if (fp == NULL)
{
printf("Open pcm file error.\n");
return -1;
//以只读方式打开文件
}
fpout = fopen("E:\\shuai_text.wav", "wb+");
if (fpout == NULL)
{
printf("Create wav file error.\n");
return -1;
}
//以读写方式打开
/* WAVE_HEADER */
memcpy(pcmHEADER.fccID, "RIFF", strlen("RIFF"));
memcpy(pcmHEADER.fccType, "WAVE", strlen("WAVE"));
fseek(fpout, sizeof(WAVE_HEADER), 1);
//1=SEEK_CUR
/* WAVE_FMT */
//进行 wav 文件初始化
memcpy(pcmFMT.fccID, "fmt ", strlen("fmt "));
pcmFMT.dwSize = 16;
pcmFMT.wFormatTag = 1;
pcmFMT.wChannels = 1;
pcmFMT.dwSamplesPerSec = sample_rate;
pcmFMT.uiBitsPerSample = bits;
/* ==dwSamplesPerSec*wChannels*uiBitsPerSample/8 */
pcmFMT.dwAvgBytesPerSec
pcmFMT.dwSamplesPerSec*pcmFMT.wChannels*pcmFMT.uiBitsPerSample / 8;
/* ==wChannels*uiBitsPerSample/8 */
pcmFMT.wBlockAlign = pcmFMT.wChannels*pcmFMT.uiBitsPerSample / 8;
fwrite(&pcmFMT, sizeof(WAVE_FMT), 1, fpout);
=
8