// DirectSoundDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "DirectSound.h"
#include "DirectSoundDlg.h"
#include <process.h>
#include <mmsystem.h>
#include <dsound.h>
//#pragma comment(lib,"dxerr9.lib")
#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"dsound.lib")
#pragma comment(lib,"dxguid.lib")
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CDirectSoundDlg 对话框
/***************************************/
LPDIRECTSOUND8 ds=NULL;
LPDIRECTSOUNDBUFFER8 dsb=NULL;
/***************************************/
CDirectSoundDlg::CDirectSoundDlg(CWnd* pParent /*=NULL*/)
: CDialog(CDirectSoundDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CDirectSoundDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CDirectSoundDlg, CDialog)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_BUTTON1, &CDirectSoundDlg::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON3, &CDirectSoundDlg::OnBnClickedButton3)
ON_BN_CLICKED(IDC_BUTTON2, &CDirectSoundDlg::OnBnClickedButton2)
END_MESSAGE_MAP()
// CDirectSoundDlg 消息处理程序
LRESULT ret;
CFile wavefile;
typedef struct
{
DWORD dwRiff; // Type of file header.
DWORD dwSize; // Size of file header.
DWORD dwWave; // Type of wave.
} RIFF_FILEHEADER, *PRIFF_FILEHEADER;
// -----------------------------------------------------------------------------
// ChunkHeader
// -----------------------------------------------------------------------------
typedef struct
{
DWORD dwCKID; // Type Identification for current chunk header.
DWORD dwSize; // Size of current chunk header.
} RIFF_CHUNKHEADER, *PRIFF_CHUNKHEADER;
BOOL CDirectSoundDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CDirectSoundDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<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 CDirectSoundDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CDirectSoundDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
WAVEFORMATEX pWFX;
pWFX.cbSize=0;
pWFX.wFormatTag=WAVE_FORMAT_PCM;
pWFX.nChannels=1;
pWFX.nSamplesPerSec=8000;
pWFX.wBitsPerSample=16;
pWFX.nAvgBytesPerSec = pWFX.nChannels * pWFX.nSamplesPerSec * pWFX.wBitsPerSample / 8;
pWFX.nBlockAlign =pWFX.wBitsPerSample * pWFX.nChannels / 8;
wavefile.Open(L"C://r.data",CFile::modeRead);
if(wavefile.m_hFile==CFile::hFileNull)
{
AfxMessageBox(L"没有找到c://r.data/n程序终止");
ExitProcess(0);
}
DWORD waveBufferSize=wavefile.GetLength();//-(sizeof(RIFF_FILEHEADER)+sizeof(RIFF_CHUNKHEADER)*2+sizeof(WAVEFORMATEX));
ret=DirectSoundCreate8(NULL,&ds,NULL);
if(FAILED(ret))
{
AfxMessageBox(L"初始化DirectSound失败");
ExitProcess(0);
}
ret=ds->SetCooperativeLevel(this->m_hWnd,DSSCL_PRIORITY);
DSBUFFERDESC csdd;
ZeroMemory(&csdd,sizeof(DSBUFFERDESC));
csdd.lpwfxFormat=&pWFX;
csdd.dwFlags=DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLFX| DSBCAPS_CTRLPOSITIONNOTIFY |DSBCAPS_GETCURRENTPOSITION2;
csdd.dwSize=sizeof(DSBUFFERDESC);
csdd.dwBufferBytes=waveBufferSize;
LPDIRECTSOUNDBUFFER pbuffer=NULL;
ret=ds->CreateSoundBuffer(&csdd,&pbuffer,NULL);
if(FAILED(ret))
{
AfxMessageBox(L"CreateSoundBuffer失败");
if(wavefile.m_hFile!=CFile::hFileNull)
wavefile.Close();
ds->Release();
ExitProcess(0);
}
ret=pbuffer->QueryInterface(IID_IDirectSoundBuffer8,(LPVOID*)&dsb);
if(FAILED(ret))
{
AfxMessageBox(L"CreateSoundBuffer失败");
if(wavefile.m_hFile!=CFile::hFileNull)
wavefile.Close();
ds->Release();
pbuffer->Release();
ExitProcess(0);
}
pbuffer->Release();
LPVOID data;
DWORD len;
DWORD writtenBytes;
ret=dsb->Lock(0,0,&data,&len,NULL,NULL,DSBLOCK_ENTIREBUFFER);
wavefile.Seek(0,CFile::begin);
writtenBytes=wavefile.Read(data,len);
ret=dsb->Unlock(data,len,NULL,NULL);
dsb->SetCurrentPosition(0);
ret=dsb->Play(0,0,0);
wavefile.Close();
}
void CDirectSoundDlg::OnClose()
{
wavefile.Close();
dsb->Release();
ds->Release();
}
#define NOTIFYS 10
#define NOTIFYSIZE 10240
LPDIRECTSOUNDCAPTURE8 g_dsc=NULL;
LPDIRECTSOUNDCAPTUREBUFFER8 g_dscb=NULL;
LPDIRECTSOUNDNOTIFY g_dsn=NULL;
DSBPOSITIONNOTIFY pn[NOTIFYS];
HANDLE hNotify[NOTIFYS];
DWORD iBufferSize;
FILE* f;
BOOL quit=FALSE;
DWORD _stdcall RecordNotify(void*)
{
DWORD r;
f=fopen("c://r.data","wb");
DWORD readpos;
LPVOID pb1,pb2;
DWORD pd1,pd2;
int locksize=0;
int iBufferOffset=0;
if(!f)
{
MessageBox(NULL,L"创建文件失败",L"",0);
return 0;
}
while(!quit)
{
/*if(r==WAIT_OBJECT_0+0)
{
if(SUCCEEDED(g_dscb->GetCurrentPosition(NULL,&cur)))
{
if(SUCCEEDED(g_dscb->Lock(0,bufferSize/2,&pb1,&pd1,NULL,NULL,0)))
{
fwrite(pb1,sizeof(char),pd1,f);
fflush(f);
}
g_dscb->Unlock(pb1,pd1,NULL,NULL);
}
}
else if(r==WAIT_OBJECT_0 + 1)
{
if(SUCCEEDED(g_dscb->GetCurrentPosition(NULL,&cur)))
{
if(SUCCEEDED(g_dscb->Lock(cur,bufferSize/2,&pb1,&pd1,NULL,NULL,0)))
{
fwrite(pb1,sizeof(char),pd1,f);
fflush(f);
}
g_dscb->Unlock(pb1,pd1,NULL,NULL);
}
}*/
WAIT_FAILED != (r=WaitForMultipleObjects(NOTIFYS,hNotify,FALSE,INFINITE));
if(quit)
break;
if(SUCCEEDED(g_dscb->GetCurrentPosition(NULL,&readpos)))
{
locksize = readpos - iBufferOffset;//这个大小就是我们可以安全读取的大小
if(locksize!=0)
{
if (locksize < 0)
{//因为我们是循环的使用缓冲区,所以有一种情况下为负:当文以载读指针回到第一个通知点,而Ibuffeoffset还在最后一个通知处
locksize += iBufferSize;
}
if(SUCCEEDED(g_dscb->Lock(iBufferOffset,locksize,&pb1,&pd1,NULL,NULL,0)))
{
fwrite(pb1,sizeof(char),pd1,f);
g_dscb->Unlock(pb1,pd1,NULL,NULL);
fflush(f);
}
iBufferOffset += pd1;
iBufferOffset %= iBufferSize;//取模是因为缓冲区是循环的。
}
}
}
fclose(f);
}
//LPDIRECTSOUND8 g_ds=NULL;
void CDirectSoundDlg::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
ret=DirectSoundCaptureCreate8(NULL,&g_dsc,NULL);
if(FAILED(ret))
{
AfxMessageBox(_T("DirectSoundCreate8失败"));
return ;
}
DSCBUFFERDESC desc;
WAVEFORMATEX wfx;
wfx.cbSize=sizeof(WAVEFORMATEX);
wfx.nChannels=1;
wfx.nSamplesPerSec=8000;
wfx.wFormatTag=WAVE_FORMAT_PCM;
wfx.wBitsPerSample=16;
wfx.nBlockAlign=2;
wfx.nAvgBytesPerSec=wfx.nSamplesPerSec*wfx.nBlockAlign;
ZeroMemory(&desc,sizeof(DSCBUFFERDESC));
desc.dwSize=sizeof(DSCBUFFERDESC);
desc.lpwfxFormat=&wfx;
desc.dwBufferBytes=iBufferSize=NOTIFYS*NOTIFYSIZE;
desc.dwFlags=0;
desc.lpDSCFXDesc=NULL;
LPDIRECTSOUNDCAPTUREBUFFER lpBuffer;
ret=g_dsc->CreateCaptureBuffer(&desc,&lpBuffer,NULL);
if(FAILED(ret))
{
AfxMessageBox(_T("创建Buffer失败"));
g_dsc->Release();
return ;
}
ret=lpBuffer->QueryInterface(IID_IDirectSoundCaptureBuffer8,(LPVOID*)&g_dscb);
if(FAILED(ret))
{
AfxMessageBox(_T("创建Buffer8失败"));
lpBuffer->Release();
g_dsc->Release();
}
lpBuffer->Release();
ret=g_dscb->QueryInterface(IID_IDirectSoundNotify,(LPVOID*)&g_dsn);
/*pn[0].dwOffset=bufferSize/2;
pn[0].hEventNotify=hNotify[0]=CreateEvent(NULL,FALSE,FALSE,NULL);
pn[1].dwOffset=DSBPN_OFFSETSTOP;
pn[1].hEventNotify=hNotify[1]=CreateEvent(NULL,FALSE,FALSE,NULL);*/
for(int i=0;i<NOTIFYS;i++)
{
pn[i].dwOffset=NOTIFYSIZE+i*NOTIFYSIZE-1;
pn[i].hEventNotify=hNotify[i]=CreateEvent(NULL,FALSE,FALSE,NULL);
}
if(SUCCEEDED(ret))
{
ret=g_dsn->SetNotificationPositions(NOTIFYS,pn);
if(FAILED(ret))
{
AfxMessageBox(_T("创建Notify失败"));
}
else
{
CreateThread(NULL,0,RecordNotify,NULL,0,NULL);
//_beginthread(RecordNotify,0,NULL);
}
g_dsn->Release();
ret=g_dscb->Start(DSCBSTART_LOOPING);
if(FAILED(ret))
{
AfxMessageBox(L"录音失败");
}
}else
{
AfxMessageBox(_T("QueryInterface失败"));
}
}
void CDirectSoundDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
if(g_dscb)
{
g_dscb->Stop();
quit=TRUE;
SetEvent(hNotify[0]);
}
}