// ACMDemoDlg.cpp : implementation file
// Download by http://www.codefans.net
#include "stdafx.h"
#include "ACMDemo.h"
#include "ACMDemoDlg.h"
#include "TagDefine.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
WAVEFORMATEX SrcFormat; //源音频格式,在AudioInit()中初始化
extern HANDLE hHeap; //堆句柄
char szFormat[ACMFORMATDETAILS_FORMAT_CHARS];
HACMDRIVERID HadID = NULL;
LPWAVEFORMATEX pDstFormat = NULL; //目的音频格式指针
HACMDRIVER Had = NULL;
HACMSTREAM HstrIn = NULL;
HACMSTREAM HstrOut = NULL;
BOOL bWaitForExit = FALSE;
//************************************
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//***********************************************
CACMDemoDlg::CACMDemoDlg(CWnd* pParent /*=NULL*/)
: CDialog(CACMDemoDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CACMDemoDlg)
//}}AFX_DATA_INIT
m_WaveHdrIndex = 0;
m_AcmHdrIndex = 0;
m_hWaveIn = NULL;
m_hWaveOut = NULL;
szFormat[0] = '\0';
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CACMDemoDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CACMDemoDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CACMDemoDlg, CDialog)
//{{AFX_MSG_MAP(CACMDemoDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_MESSAGE(MM_WIM_DATA,OnMmWimData)
ON_MESSAGE(MM_WOM_DONE,OnMmWomDone)
ON_MESSAGE(WM_USER_ACMINCMPLT,OnAcmInCmplt)
ON_MESSAGE(WM_USER_ACMOUTCMPLT,OnAcmOutCmplt)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CACMDemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
SetIcon(m_hIcon, TRUE);
SetIcon(m_hIcon, FALSE);
if(AudioInit() != TRUE) //音频初始化
OnCancel();
return TRUE;
}
void CACMDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
CDialog::OnSysCommand(nID, lParam);
}
void CACMDemoDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this);
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
dc.DrawIcon(x, y, m_hIcon);
}
else
CDialog::OnPaint();
}
HCURSOR CACMDemoDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CACMDemoDlg::OnOK()
{
waveInStart(m_hWaveIn);
GetDlgItem(IDOK)->EnableWindow(FALSE);
}
void CACMDemoDlg::OnCancel()
{
bWaitForExit = TRUE;
AudioStop();
CDialog::OnCancel();
}
//*************************** Audio In *******************************************
BOOL CALLBACK acmFormatEnumCallback(HACMDRIVERID hadid,
LPACMFORMATDETAILS pafd, DWORD dwInstance, DWORD fdwSupport)
{
if(lstrcmp(pafd->szFormat,szFormat) == 0)
{
HadID = hadid;
SAFE_HEAPFREE(pDstFormat);
pDstFormat = (LPWAVEFORMATEX)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(WAVEFORMATEX)+pafd->pwfx->cbSize);
if(pDstFormat == NULL)
return TRUE; //继续搜索
memcpy(pDstFormat, pafd->pwfx, sizeof(WAVEFORMATEX) + pafd->pwfx->cbSize);
return FALSE; //完成
}
return TRUE; //继续搜索
}
BOOL CALLBACK acmDriverEnumCallback(HACMDRIVERID hadid, DWORD dwInstance,
DWORD fdwSupport)
{
if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC)
{
MMRESULT mmr;
HACMDRIVER had = NULL;
mmr = acmDriverOpen(&had, hadid, 0);
if(mmr != 0)
return TRUE;
DWORD dwSize;
mmr = acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize);
if(mmr != 0)
{
acmDriverClose(had, 0);
return TRUE;
}
WAVEFORMATEX* pwf = (WAVEFORMATEX*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwSize);
if(pwf == NULL)
{
acmDriverClose(had, 0);
return TRUE;
}
pwf->cbSize = LOWORD(dwSize) - sizeof(WAVEFORMATEX);
pwf->wFormatTag = WAVE_FORMAT_UNKNOWN;
ACMFORMATDETAILS* paftd = (ACMFORMATDETAILS*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(ACMFORMATDETAILS));
if(paftd == NULL)
{
SAFE_HEAPFREE(pwf);
acmDriverClose(had, 0);
return TRUE;
}
paftd->cbStruct = sizeof(ACMFORMATDETAILS);
paftd->pwfx = pwf;
paftd->cbwfx = dwSize;
paftd->dwFormatTag = WAVE_FORMAT_UNKNOWN;
mmr = acmFormatEnum(had, paftd, acmFormatEnumCallback, 0, 0);
SAFE_HEAPFREE(pwf);
SAFE_HEAPFREE(paftd);
acmDriverClose(had, 0);
if(mmr != 0)
return TRUE;
}
if(HadID != NULL)
return FALSE; //找到了合适的 CODEC , 返回
return TRUE; //否则继续搜索
}
BOOL CACMDemoDlg::AudioInit()
{
MMRESULT mmr;
SrcFormat.wFormatTag = WAVE_FORMAT_PCM; //源音频格式
SrcFormat.nChannels = 1;
SrcFormat.nSamplesPerSec = 8000;
SrcFormat.nAvgBytesPerSec = 8000;
SrcFormat.nBlockAlign = 1;
SrcFormat.wBitsPerSample = 8;
SrcFormat.cbSize = 0;
mmr = waveInOpen(&m_hWaveIn, WAVE_MAPPER, &SrcFormat, (UINT)m_hWnd, 0, CALLBACK_WINDOW);
if(mmr != MMSYSERR_NOERROR) //打开音频输入设备
{
::MessageBox(m_hWnd,MSG_WAVEINERR,MSG_ERRTITLE,MB_OK | MB_ICONWARNING | MB_DEFBUTTON1);
return FALSE;
}
mmr = waveOutOpen(&m_hWaveOut, WAVE_MAPPER, &SrcFormat, (UINT)m_hWnd, 0L, CALLBACK_WINDOW);
if(mmr != MMSYSERR_NOERROR) //打开音频输出设备
{
::MessageBox(m_hWnd,MSG_WAVEOUTERR,MSG_ERRTITLE,MB_OK | MB_ICONWARNING | MB_DEFBUTTON1);
return FALSE;
}
ACMFORMATCHOOSE acmfc;
memset(&acmfc, 0, sizeof(acmfc));
for(;;)
{
SAFE_HEAPFREE(pDstFormat);
pDstFormat = (LPWAVEFORMATEX)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(WAVEFORMATEX) + 32);
pDstFormat->wFormatTag = 49; //GSM 6.10 // 34 //TrueSpeech
pDstFormat->nChannels = 1; // 1
pDstFormat->nSamplesPerSec = 8000; // 8000
pDstFormat->nAvgBytesPerSec = 1625; // 1067
pDstFormat->nBlockAlign = 65; // 32
pDstFormat->wBitsPerSample = 0; // 1
pDstFormat->cbSize = 32; // 2 // 32
//此处的 pDstFormat 是默认的格式. GSM 6.10 对应的 cbSize 是 2 .这里之所以
//要设为 32 是因为如果设为 2 而用户又另选了一个 cbSize 大于 2 的格式,就会
//返回一个 ACMERR_NOTPOSSIBLE 错误.
acmfc.cbStruct = sizeof(acmfc);
acmfc.fdwStyle = ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT;
acmfc.hwndOwner = NULL;
acmfc.pwfx = pDstFormat;
acmfc.cbwfx = (pDstFormat->cbSize) + sizeof(WAVEFORMATEX);
acmfc.pszTitle = MSG_FORMATCHOOSETITLE;
acmfc.szFormatTag[0] = '\0';
acmfc.szFormat[0] = '\0';
acmfc.pszName = NULL;
acmfc.cchName = 0;
acmfc.fdwEnum = ACM_FORMATENUMF_NCHANNELS | ACM_FORMATENUMF_NSAMPLESPERSEC;
acmfc.pwfxEnum = &SrcFormat;
acmfc.hInstance = NULL;
acmfc.pszTemplateName = NULL;
acm