📄 dialog_study.cpp
字号:
// Dialog_Study.cpp : implementation file
//
#include "stdafx.h"
#include "VoiceCtrl.h"
#include "Dialog_Study.h"
#include "Afxwin.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//#pragma comment(lib, "winmm.lib")
/////////////////////////////////////////////////////////////////////////////
// Dialog_Study dialog
Dialog_Study::Dialog_Study(CWnd* pParent /*=NULL*/)
: CDialog(Dialog_Study::IDD, pParent)
{
//{{AFX_DATA_INIT(Dialog_Study)
m_name = _T("");
m_information = _T("");
m_command = _T("");
//}}AFX_DATA_INIT
pWaveHdr1=reinterpret_cast<PWAVEHDR>(malloc(sizeof(WAVEHDR)));
pWaveHdr2=reinterpret_cast<PWAVEHDR>(malloc(sizeof(WAVEHDR)));
pSaveBuffer = reinterpret_cast<PBYTE>(malloc(1));
//m_ctrl_command.ShowDropDown(true);
//m_ctrl_command.
}
void Dialog_Study::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(Dialog_Study)
DDX_Control(pDX, IDC_COMBO_Command, m_ctrl_command);
DDX_Control(pDX, IDC_EDIT_Information, m_Ctrl_Info);
DDX_Text(pDX, IDC_EDIT_Name, m_name);
DDV_MaxChars(pDX, m_name, 20);
DDX_Text(pDX, IDC_EDIT_Information, m_information);
DDV_MaxChars(pDX, m_information, 50);
DDX_CBString(pDX, IDC_COMBO_Command, m_command);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(Dialog_Study, CDialog)
//{{AFX_MSG_MAP(Dialog_Study)
ON_BN_CLICKED(IDC_BUTTON_Record, OnBUTTONRecord)
ON_BN_CLICKED(IDC_BUTTON_Play, OnBUTTONPlay)
ON_MESSAGE(MM_WIM_OPEN,OnMM_WIM_OPEN)
ON_MESSAGE(MM_WIM_DATA,OnMM_WIM_DATA)
ON_MESSAGE(MM_WIM_CLOSE,OnMM_WIM_CLOSE)
ON_MESSAGE(MM_WOM_OPEN,OnMM_WOM_OPEN)
ON_MESSAGE(MM_WOM_DONE,OnMM_WOM_DONE)
ON_MESSAGE(MM_WOM_CLOSE,OnMM_WOM_CLOSE)
ON_WM_TIMER()
ON_BN_CLICKED(IDC_BUTTON_Stop, OnBUTTONStop)
ON_BN_CLICKED(IDC_BUTTON_Save, OnBUTTONSave)
//ON_CBN_SETFOCUS(IDC_COMBO_Command, OnSetfocusCOMBOCommand)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// Dialog_Study message handlers
//开始 学习 录音
void Dialog_Study::OnBUTTONRecord()
{
// TODO: Add your control notification handler code here
// MessageBox(_T("Dialog_Study::OnBUTTONRecord() "));
//(CButton *)GetDlgItem(IDC_BUTTON_Play);
pBuffer1=(PBYTE)malloc(INP_BUFFER_SIZE); //分配buffer1
pBuffer2=(PBYTE)malloc(INP_BUFFER_SIZE); //分配buffer2
if (!pBuffer1 || !pBuffer2) //如果某一个缓存分配失败,则都释放,提示,然后返回
{
if (pBuffer1) free(pBuffer1);
if (pBuffer2) free(pBuffer2);
MessageBeep(MB_ICONEXCLAMATION); //???????????
AfxMessageBox(_T("Memory erro!")); //
return ;
}
//写打开一个波形文件 CFile outWaveFile
outWaveFile.Open(_T("temp.wav"),CFile::modeCreate|CFile::modeWrite);
//初始化 waveheader文件头
WvH.dwSamplingRate = 11025; //
WvH.dwRIFF = 0x46464952; //groupid
WvH.dwWAVE = 0x45564157;
WvH.dw_fmt = 0x20746d66;
WvH.dwFmtLen = 0x14;
WvH.wDataType = 1;
WvH.wNChannels = 1;
WvH.wNBitsPerSam = 8;
// 1
WvH.wAlignment = WvH.wNChannels * WvH.wNBitsPerSam / 8;
WvH.dwNBytesPerSec = WvH.dwSamplingRate * WvH.wAlignment * WvH.wNChannels;
WvH.cbSize=0x02;
//WvH.TE03=0xff;
WvH.dwfact=0x74636166;
WvH.dwtest=0x00000004;
WvH.test1=0xbc4c;
WvH.test2=0x0001;
WvH.dwdata = 0x61746164; //"data"
WvH.dwDataLen=0;//dwDataLength;
WvH.dwFileLen=WvH.dwDataLen +50;
outWaveFile.Seek(0,CFile::begin); //定位到文件开始部位
outWaveFile.Write(&WvH,sizeof(WAVEHEADER)); //把wave 文件头写入波形文件
//open waveform audio for input
//打开waveform ,设置录音格式
waveform.wFormatTag=WAVE_FORMAT_PCM;
waveform.nChannels=1;
waveform.nSamplesPerSec=11025;
waveform.nAvgBytesPerSec=11025;
waveform.nBlockAlign=1;
waveform.wBitsPerSample=8;
waveform.cbSize=0; //
if (waveInOpen(&hWaveIn, //设备文件地址
WAVE_MAPPER, //波形输入设备打开标记
&waveform, //指向已经定义的 WAVEFORMATEX 结构
(DWORD)this->m_hWnd, //
NULL, //
CALLBACK_WINDOW)) //The dwCallback parameter is a window handle
{ //如果打开失败。。。。。
free(pBuffer1);
free(pBuffer2);
MessageBeep(MB_ICONEXCLAMATION);
AfxMessageBox(_T("Audio can not be open!"));
return ;
}
//如果打开成功了:
//pWaveHdr1是指向wavehdr数据结构的指针,用于建立起音频输入设备和数据接收缓冲区之间的联系
//
pWaveHdr1->lpData=(LPSTR)pBuffer1; //缓冲区地址
pWaveHdr1->dwBufferLength=INP_BUFFER_SIZE; //缓冲区长度
pWaveHdr1->dwBytesRecorded=0; //
pWaveHdr1->dwUser=0;
pWaveHdr1->dwFlags=0;
pWaveHdr1->dwLoops=1;
pWaveHdr1->lpNext=NULL;
pWaveHdr1->reserved=0;
// MessageBox(_T("7"));
//waveInPrepareHeader函数用于为音频输入设备 准备wavehdr数据结构,该数据结构在录音时
//指定录音数据暂存缓冲区和缓冲区的大小
waveInPrepareHeader(hWaveIn,pWaveHdr1,sizeof(WAVEHDR));
pWaveHdr2->lpData=(LPSTR)pBuffer2;
pWaveHdr2->dwBufferLength=INP_BUFFER_SIZE;
pWaveHdr2->dwBytesRecorded=0;
pWaveHdr2->dwUser=0;
pWaveHdr2->dwFlags=0;
pWaveHdr2->dwLoops=1;
pWaveHdr2->lpNext=NULL;
pWaveHdr2->reserved=0;
//同上 ,乒乓缓冲的方法
waveInPrepareHeader(hWaveIn,pWaveHdr2,sizeof(WAVEHDR));
//////////////////////////////////////////////////////////////////////////
pSaveBuffer = (PBYTE)realloc (pSaveBuffer, 100) ; //??????????
// Add the buffers
//为音频输入添加缓冲区并启动录音
waveInAddBuffer (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ;//将缓冲区地址和输入设备相关联
waveInAddBuffer (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ;
// Begin sampling
bRecording = TRUE ;
bEnding = FALSE ;
dwDataLength = 0 ;
// MessageBox(_T("3"));
//启动
waveInStart (hWaveIn) ;
GetDlgItem(IDC_BUTTON_Record)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_Play)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_Save)->EnableWindow(FALSE);
SetTimer(1,2000,NULL);
}
void Dialog_Study::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
CDialog::OnTimer(nIDEvent);
KillTimer(1);
GetDlgItem(IDC_BUTTON_Record)->EnableWindow(TRUE);
GetDlgItem(IDC_BUTTON_Play)->EnableWindow(TRUE);
GetDlgItem(IDC_BUTTON_Save)->EnableWindow(TRUE);
Dialog_Study::OnBUTTONStop();
CDialog::OnTimer(nIDEvent);
}
void Dialog_Study::OnBUTTONStop()
{
// TODO: Add your control notification handler code here
//MessageBox(_T("Close"));
bEnding=TRUE;
bRecording=FALSE;
//Sleep(1500);
WvH.dwDataLen=dwDataLength;
WvH.dwFileLen=WvH.dwDataLen +50;//+ 16 + 20;
outWaveFile.SeekToBegin();
outWaveFile.Write(&WvH,sizeof(WAVEHEADER));
waveInReset(hWaveIn); //停止录音
outWaveFile.Close(); //???????????????????????????
}
void Dialog_Study::OnMM_WIM_OPEN(UINT wParam, LONG lParam)
{ //一开始录音,就自动调用这个
// TODO: Add your message handler code here and/or call default
//MessageBox(_T("luyin"));
//SetTimer(1,100,NULL); //设置定时器1 为100ms
bRecording=TRUE;
bEnding=FALSE;
// MessageBox(_T("OnMM_WIM_OPEN"));
//TRACE( L"dddd\n" );
}
void Dialog_Study::OnMM_WIM_DATA(UINT wParam, LONG lParam)
{
//缓冲区用完时,自动调用这个回调函数
// MessageBox(_T("OnMM_WIM_DATA"));
// TODO: Add your message handler code here and/or call default
// Reallocate save buffer memory
if(bEnding){
waveInClose(hWaveIn); //关闭录音
//MessageBox(_T("OnMM_WIM_DATA wrong 11111"));
return;
}
//////////////////////////////////////////////////////////////////////////
pNewBuffer =(PBYTE)realloc(pSaveBuffer, dwDataLength +((PWAVEHDR) lParam)->dwBytesRecorded) ;
if (pNewBuffer == NULL)
{
waveInClose (hWaveIn) ;
MessageBeep (MB_ICONEXCLAMATION) ;
AfxMessageBox(_T("erro memory"));
return ;
}
pSaveBuffer = pNewBuffer ;
//TRACE( L"This is pNewBuffer: %s\n",pNewBuffer );
CopyMemory (pSaveBuffer + dwDataLength, //目的 //????????why to add dwDataLength??
((PWAVEHDR) lParam)->lpData, //源
((PWAVEHDR) lParam)->dwBytesRecorded) ; //长度
dwDataLength += ((PWAVEHDR) lParam)->dwBytesRecorded ;
//写入文件
outWaveFile.SeekToEnd();
outWaveFile.Write(pSaveBuffer,((PWAVEHDR) lParam)->dwBytesRecorded);
//LPMMIOINFO lpmmioinfo;
//mmioOpen( _T("temp.wav"), lpmmioinfo,MMIO_CREATE);
// Send out a new buffer //添加新的缓冲区
//(PWAVEHDR)lParam->lpData;
((PWAVEHDR) lParam)->lpData=NULL;
waveInAddBuffer (hWaveIn, (PWAVEHDR) lParam, sizeof (WAVEHDR)) ;
// TRACE(_T("done input data\n"));
return ;
}
void Dialog_Study::OnMM_WIM_CLOSE(UINT wParam, LONG lParam)
{
//MessageBox(_T("OnMM_WIM_CLOSE"));
// TODO: Add your message handler code here and/or call default
// KillTimer(1); //关闭定时器
//TRACE("MM_WIM_CLOSE\n");
if (0==dwDataLength) {
return;
}
//在停止录音之后,调用调用下面的函数,断开wavehdr数据结构和音频输入设备的联系
waveInUnprepareHeader (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ;
waveInUnprepareHeader (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ;
//释放缓冲区
free(pBuffer1) ;
free(pBuffer2) ;
//free(pSaveBuffer);
//free(pNewBuffer);
if (dwDataLength > 0) //如果声音文件有数据(可以播放)
{
// MessageBox(_T("Yes"));
}
else{
MessageBox(_T("wave file was bad!"));
}
//bRecording = FALSE ;
return ;
}
//播放
void Dialog_Study::OnBUTTONPlay()
{
// TODO: Add your control notification handler code here
//MessageBox(_T("OnBUTTONPlay() "));
//sndPlaySound(_T("temp.wav"),SND_ASYNC); //!!!!!!!!!!
if (bPlaying)
{
waveOutReset(hWaveOut);
}
//open waveform audio for output
waveform.wFormatTag = WAVE_FORMAT_PCM;
waveform.nChannels = 1;
waveform.nSamplesPerSec =11025;
waveform.nAvgBytesPerSec=11025;
waveform.nBlockAlign =1;
waveform.wBitsPerSample =8;
waveform.cbSize =0;
if (waveOutOpen(&hWaveOut,WAVE_MAPPER,&waveform,(DWORD)this->m_hWnd,NULL,CALLBACK_WINDOW))
{
MessageBeep(MB_ICONEXCLAMATION);
AfxMessageBox(_T("Audio output erro"));
}
return ;
}
//打开声音,播放
void Dialog_Study::OnMM_WOM_OPEN(UINT wParam, LONG lParam){
pWaveHdr1->lpData = (LPSTR)pSaveBuffer ;
pWaveHdr1->dwBufferLength = dwDataLength ;
pWaveHdr1->dwBytesRecorded = 0 ;
pWaveHdr1->dwUser = 0 ;
pWaveHdr1->dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP ;
pWaveHdr1->dwLoops = 1;//dwRepetitions ;
pWaveHdr1->lpNext = NULL ;
pWaveHdr1->reserved = 0 ;
// Prepare and write
//打开音频输出设备
waveOutPrepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
waveOutWrite (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
bEnding = FALSE ;
bPlaying = TRUE ;
}
//打开完成
void Dialog_Study::OnMM_WOM_DONE(UINT wParam, LONG lParam){
// MessageBox(_T("OnMM_WOM_DONE"));
//TRACE("open MM_WOM_DONE\n");
waveOutUnprepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
waveOutClose (hWaveOut) ;
bPaused = FALSE ;
dwRepetitions = 1 ;
bPlaying = FALSE ;
return ;
}
void Dialog_Study::OnMM_WOM_CLOSE(UINT wParam, LONG lParam){
// TRACE("open MM_WOM_CLOSE\n");
// MessageBox(_T("OnMM_WOM_CLOSE"));
bPaused = FALSE ;
dwRepetitions = 1 ;
bPlaying = FALSE ;
// MessageBox(_T("5"));
return ;
}
void Dialog_Study::OnBUTTONSave()
{
int status=0;
CString dataBaseFileName;
// TODO: Add your control notification handler code here
//把这个声音文件保存成一个数据库的名字 , 然后在文本文件中存储相应的信息
//1 改写文本文件
status=WriteFile();
if(0==status)
{
return; //错误 ,返回
}
//2 存储声音文件
UpdateData(true);
//outWaveFile.Close(); //关闭文件
dataBaseFileName=m_name;
CopyFile(_T("temp.wav") , dataBaseFileName , FALSE);
DeleteFile(_T("temp.wav"));
Dialog_Study::OnOK();
//MessageBox(dataBaseFileName);
}
void Dialog_Study::OnOK()
{
// TODO: Add extra validation here
//delete temp.wav
CFile file;
if(file.Open(_T("temp.wav"),CFile::modeRead,NULL))
{
file.Close();
DeleteFile(_T("temp.wav"));
}
CDialog::OnOK();
}
int Dialog_Study::WriteFile(){
int length=0 ;
CString command; //命令
CString meaning; //含义
CString filename; //文件名
int i=0;
CFile file;
UpdateData(true);
command = m_command;
filename= m_name;
meaning = m_information;
/*1 判断
字符串是否空
文件是否已经存在
*/
if(command.IsEmpty()){//IsEmpty()Return Nonzero if object has 0 length; otherwise 0.
MessageBox(_T("Command Cannot be empty!"),_T("wrong!"),MB_OK);
return 0;
}
if(filename.IsEmpty()){//IsEmpty()Return Nonzero if object has 0 length; otherwise 0.
MessageBox(_T("Filename Cannot be empty!"),_T("wrong!"),MB_OK);
return 0;
}
if(meaning.IsEmpty()){//IsEmpty()Return Nonzero if object has 0 length; otherwise 0.
MessageBox(_T("Information Cannot be empty!"),_T("wrong!"),MB_OK);
return 0;
}
if(file.Open(filename,CFile::modeRead,NULL))
{
MessageBox(_T("wen jian yijing cunzai!"),_T("wrong!"),MB_OK);
file.Close();
return 0;
}
if(!file.Open(_T("temp.wav"),CFile::modeRead,NULL))
{
MessageBox(_T("Cannot find the source wave file!"),_T("wrong!"),MB_OK);
return 0;
}else{
file.Close();
}
//2
file.Open(_T("database.txt"),CFile::modeNoTruncate |CFile::modeCreate|CFile::modeWrite); //database.txt
file.SeekToEnd();
length=2*command.GetLength();
file.Write(_T("command=")+command+_T("\r\n"),16+length+4); //写 command
length=2*filename.GetLength();
file.Write(_T("filename=")+filename+_T("\r\n"),18+length+4);//写 filename
length=2*meaning.GetLength();
file.Write(_T("meaning=")+meaning+_T("\r\n"),16+length+4);
file.Close();
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -